sumba 1.0.21 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bajo/hook/dobo.sumba-user@after-record-update.js +22 -6
- package/bajo/hook/dobo.sumba-user@after-record-validation.js +1 -1
- package/bajo/intl/en-US.json +8 -6
- package/bajo/intl/id.json +8 -6
- package/dobo/schema/user.json +1 -1
- package/package.json +1 -1
- package/waibuMpa/partial/_mail/mystuff-change-password.html +3 -0
- package/waibuMpa/partial/_mail/mystuff-change-password.id.html +3 -0
- package/waibuMpa/partial/_mail/mystuff-reset-api-key.html +3 -0
- package/waibuMpa/partial/_mail/mystuff-reset-api-key.id.html +4 -0
- package/waibuMpa/partial/my-stuff/profile/edit.html +2 -2
- package/waibuMpa/partial/my-stuff/profile/view.html +1 -1
- package/waibuMpa/partial/my-stuff/reset-api-key.html +10 -12
- package/waibuMpa/route/help/trouble-tickets/details/@id.js +0 -1
- package/waibuMpa/route/my-stuff/change-password.js +2 -2
- package/waibuMpa/route/my-stuff/profile/edit.js +14 -10
- package/waibuMpa/route/my-stuff/profile.js +2 -1
- package/waibuMpa/route/my-stuff/reset-api-key.js +3 -3
- package/waibuMpa/route/user/forgot-password/@fpl.js +0 -1
- package/waibuMpa/template/_mail/mystuff-change-password.html +3 -0
- package/waibuMpa/template/_mail/mystuff-reset-api-key.html +3 -0
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
async function afterRecordUpdate (id, body, options = {}, rec) {
|
|
2
2
|
if (!(this.app.masohi && this.app.masohiMail)) return
|
|
3
|
+
|
|
3
4
|
const { data, oldData } = rec
|
|
4
|
-
if (!(oldData.status === 'UNVERIFIED' && data.status === 'ACTIVE')) return
|
|
5
|
-
options.tpl = 'sumba.template:/_mail/user-activation-success.html'
|
|
6
5
|
const to = `${data.firstName} ${data.lastName} <${data.email}>`
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
let subject
|
|
7
|
+
|
|
8
|
+
async function send () {
|
|
9
|
+
try {
|
|
10
|
+
await this.app.masohi.send({ to, subject, message: data, options })
|
|
11
|
+
} catch (err) {
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
if (oldData.status === 'UNVERIFIED' && data.status === 'ACTIVE') {
|
|
15
|
+
subject = options.req.t('userActivation')
|
|
16
|
+
options.tpl = 'sumba.template:/_mail/user-activation-success.html'
|
|
17
|
+
await send()
|
|
18
|
+
} else if (oldData.token !== data.token) {
|
|
19
|
+
subject = options.req.t('resetApiKey')
|
|
20
|
+
options.tpl = 'sumba.template:/_mail/mystuff-reset-api-key.html'
|
|
21
|
+
await send()
|
|
22
|
+
} else if (body.password) {
|
|
23
|
+
subject = options.req.t('changePassword')
|
|
24
|
+
options.tpl = 'sumba.template:/_mail/mystuff-change-password.html'
|
|
25
|
+
await send()
|
|
26
|
+
}
|
|
11
27
|
}
|
|
12
28
|
|
|
13
29
|
export default afterRecordUpdate
|
|
@@ -3,7 +3,7 @@ async function doboSumbaUserAfterRecordValidation (body, options) {
|
|
|
3
3
|
const { has } = this.app.bajo.lib._
|
|
4
4
|
|
|
5
5
|
if (has(body, 'password') && !isBcrypt(body.password)) body.password = await hash(body.password, 'bcrypt')
|
|
6
|
-
if (has(body, 'token') && !isMd5(body.token)) body.token = await hash(body.password)
|
|
6
|
+
if (has(body, 'token') && !isMd5(body.token)) body.token = await hash(body.password ?? body.token)
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export default doboSumbaUserAfterRecordValidation
|
package/bajo/intl/en-US.json
CHANGED
|
@@ -87,11 +87,13 @@
|
|
|
87
87
|
"cat": "Category"
|
|
88
88
|
},
|
|
89
89
|
"validation": {
|
|
90
|
-
"password
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
"password": {
|
|
91
|
+
"minOfUppercase": "Contains at leaset %(min)s uppercase characters",
|
|
92
|
+
"minOfSpecialCharacters": "Contains at least %(min)s special characters",
|
|
93
|
+
"minOfLowercase": "Contains at least %(min)s special characters",
|
|
94
|
+
"minOfNumeric": "Contains at least %(min)s numerical characters",
|
|
95
|
+
"noWhiteSpaces": "No space allowed",
|
|
96
|
+
"onlyLatinCharacters": "Only latin characters allowed"
|
|
97
|
+
}
|
|
96
98
|
}
|
|
97
99
|
}
|
package/bajo/intl/id.json
CHANGED
|
@@ -89,11 +89,13 @@
|
|
|
89
89
|
"cat": "Kategori"
|
|
90
90
|
},
|
|
91
91
|
"validation": {
|
|
92
|
-
"password
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
"password": {
|
|
93
|
+
"minOfUppercase": "Mengandung setidaknya %(min)s huruf besar",
|
|
94
|
+
"minOfSpecialCharacters": "Mengandung setidaknya %(min)s karakter spesial",
|
|
95
|
+
"minOfLowercase": "Mengandung setidaknya %(min)s huruf kecil",
|
|
96
|
+
"minOfNumeric": "Mengandung setidaknya %(min)s numerik/angka",
|
|
97
|
+
"noWhiteSpaces": "Tidak boleh ada spasi",
|
|
98
|
+
"onlyLatinCharacters": "Harus berupa karakter latin saja"
|
|
99
|
+
}
|
|
98
100
|
}
|
|
99
101
|
}
|
package/dobo/schema/user.json
CHANGED
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<c:form referer>
|
|
1
|
+
<c:form referer enctype="multipart/form-data">
|
|
2
2
|
<c:grid-row>
|
|
3
3
|
<c:grid-col col="8-md">
|
|
4
4
|
<c:fieldset t:legend="meta" grid-gutter="2" margin="bottom-3">
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
</c:grid-col>
|
|
25
25
|
<c:grid-col col="4-md">
|
|
26
26
|
<c:heading type="5" t:content="image" />
|
|
27
|
-
<c:img
|
|
27
|
+
<c:img src="dobo:/attachment/SumbaUser/<%= form.id %>/profile/main.png" responsive rounded />
|
|
28
28
|
<c:form-file name="image" no-label wrapper-margin="top-2"/>
|
|
29
29
|
<c:btn-group margin="top-3" flex="full">
|
|
30
30
|
<c:btn type="reset" t:content="reset" color="secondary" />
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
</c:grid-col>
|
|
24
24
|
<c:grid-col col="4-md">
|
|
25
25
|
<c:heading type="5" t:content="image" />
|
|
26
|
-
<c:img
|
|
26
|
+
<c:img src="dobo:/attachment/SumbaUser/<%= form.id %>/profile/main.png" responsive rounded />
|
|
27
27
|
<c:heading type="5" t:content="more" margin="top-3" />
|
|
28
28
|
<c:list type="group" hover>
|
|
29
29
|
<c:list-item href="sumba:/my-stuff/profile/edit" t:content="updateProfile" />
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
<c:
|
|
2
|
-
<c:
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<c:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
</c:list>
|
|
12
|
-
<% } %>
|
|
1
|
+
<c:grid-row>
|
|
2
|
+
<c:grid-col col="6-md">
|
|
3
|
+
<c:form button reset-validation>
|
|
4
|
+
<c:form-plaintext name="apiKey" label-floating wrapper-margin="bottom-2" />
|
|
5
|
+
<c:form-password name="password" label-floating wrapper-margin="bottom-3" />
|
|
6
|
+
</c:form>
|
|
7
|
+
</c:grid-col>
|
|
8
|
+
<c:grid-col col="6-md">
|
|
9
|
+
</c:grid-col>
|
|
10
|
+
</c:grid-row>
|
|
@@ -14,7 +14,6 @@ const id = {
|
|
|
14
14
|
if (req.method === 'POST') {
|
|
15
15
|
try {
|
|
16
16
|
form.masterId = master.id + ''
|
|
17
|
-
console.log(form, master)
|
|
18
17
|
await recordCreate({ model: 'SumbaTicketDetail', req, body: form })
|
|
19
18
|
return reply.redirectTo('sumba:/help/trouble-tickets/list')
|
|
20
19
|
} catch (err) {
|
|
@@ -23,10 +23,10 @@ const profile = {
|
|
|
23
23
|
} catch (err) {
|
|
24
24
|
throw this.error('validationError', { details: err.details, values: err.values, ns: this.name, statusCode: 422, code: 'DB_VALIDATION' })
|
|
25
25
|
}
|
|
26
|
-
const rec = await recordGet(model, req.user.id)
|
|
26
|
+
const rec = await recordGet(model, req.user.id, { forceNoHidden: true })
|
|
27
27
|
const verified = await bcrypt.compare(req.body.currentPassword, rec.password)
|
|
28
28
|
if (!verified) throw this.error('invalidCurrentPassword', { details: [{ field: 'currentPassword', error: 'invalidPassword' }], statusCode: 400 })
|
|
29
|
-
await recordUpdate(model, req.user.id, { password: req.body.newPassword }, { req, noFlash: true })
|
|
29
|
+
await recordUpdate(model, req.user.id, { password: req.body.newPassword }, { req, reply, noFlash: true })
|
|
30
30
|
// signout and redirect to signin
|
|
31
31
|
req.session.user = null
|
|
32
32
|
req.flash('notify', req.t('passwordChangedReSignin'))
|
|
@@ -2,29 +2,33 @@ const profile = {
|
|
|
2
2
|
method: ['GET', 'POST'],
|
|
3
3
|
handler: async function (req, reply) {
|
|
4
4
|
const { defaultsDeep } = this.app.bajo
|
|
5
|
-
const { attachmentCopyUploaded } = this.app.dobo
|
|
5
|
+
// const { attachmentCopyUploaded } = this.app.dobo
|
|
6
6
|
const { recordUpdate, recordGet } = this.app.waibuDb
|
|
7
|
-
const {
|
|
7
|
+
const { omit, pick } = this.app.bajo.lib._
|
|
8
8
|
const { hash } = this.app.bajoExtra
|
|
9
9
|
const resp = await recordGet({ model: 'SumbaUser', req, id: req.user.id, options: { forceNoHidden: true, noHook: true, noCache: true } })
|
|
10
|
-
let form = defaultsDeep(req.body, resp.data)
|
|
10
|
+
let form = defaultsDeep(req.body, omit(resp.data, ['password']))
|
|
11
|
+
form.token = await hash(form.token)
|
|
11
12
|
let error
|
|
12
13
|
if (req.method === 'POST') {
|
|
13
14
|
try {
|
|
15
|
+
/*
|
|
14
16
|
if (has(req.body, 'profile')) {
|
|
15
|
-
const opts = { req, setField: 'profile', setFile: 'main.png' }
|
|
17
|
+
const opts = { req, setField: 'profile', setFile: 'main.png', noFlash: true }
|
|
16
18
|
await attachmentCopyUploaded('SumbaUser', req.user.id, opts)
|
|
17
19
|
} else {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
20
|
+
*/
|
|
21
|
+
const body = pick(form, ['firstName', 'lastName', 'address1', 'address2', 'city', 'zipCode', 'provinceState', 'country', 'phone', 'website'])
|
|
22
|
+
const options = { noFlash: true, hidden: [], setField: 'profile', setFile: 'main.png' }
|
|
23
|
+
const resp = await recordUpdate({ req, reply, model: 'SumbaUser', id: req.user.id, body, options })
|
|
24
|
+
form = resp.data
|
|
25
|
+
req.flash('notify', req.t('profileUpdated'))
|
|
26
|
+
return reply.redirectTo('sumba:/my-stuff/profile')
|
|
27
|
+
// }
|
|
22
28
|
} catch (err) {
|
|
23
|
-
console.log(err)
|
|
24
29
|
error = err
|
|
25
30
|
}
|
|
26
31
|
}
|
|
27
|
-
if (form.token) form.token = await hash(form.token)
|
|
28
32
|
return reply.view('sumba.template:/my-stuff/profile/edit.html', { form, error })
|
|
29
33
|
}
|
|
30
34
|
}
|
|
@@ -3,7 +3,8 @@ const profile = {
|
|
|
3
3
|
handler: async function (req, reply) {
|
|
4
4
|
const { hash } = this.app.bajoExtra
|
|
5
5
|
const { recordGet } = this.app.waibuDb
|
|
6
|
-
const
|
|
6
|
+
const options = { forceNoHidden: true, noHook: true, noCache: true, attachment: true, mimeType: true }
|
|
7
|
+
const resp = await recordGet({ model: 'SumbaUser', req, id: req.user.id, options })
|
|
7
8
|
const form = resp.data
|
|
8
9
|
form.token = await hash(form.token)
|
|
9
10
|
return reply.view('sumba.template:/my-stuff/profile/view.html', { form })
|
|
@@ -20,13 +20,13 @@ const resetApiKey = {
|
|
|
20
20
|
} catch (err) {
|
|
21
21
|
throw this.error('validationError', { details: err.details, values: err.values, ns: this.name, statusCode: 422, code: 'DB_VALIDATION' })
|
|
22
22
|
}
|
|
23
|
-
const rec = await recordGet(model, req.user.id)
|
|
23
|
+
const rec = await recordGet(model, req.user.id, { forceNoHidden: true })
|
|
24
24
|
const verified = await bcrypt.compare(req.body.password, rec.password)
|
|
25
25
|
if (!verified) throw this.error('validationError', { details: [{ field: 'password', error: 'invalidPassword' }], statusCode: 400 })
|
|
26
|
-
await recordUpdate(model, req.user.id, { token: generateId() })
|
|
26
|
+
await recordUpdate(model, req.user.id, { token: generateId() }, { req, reply, noFlash: true })
|
|
27
27
|
await delay(2000) // ensure req.user cache is expired
|
|
28
28
|
req.flash('notify', req.t('resetApiKeySuccessfull'))
|
|
29
|
-
return reply.redirectTo('sumba:/profile')
|
|
29
|
+
return reply.redirectTo('sumba:/my-stuff/profile')
|
|
30
30
|
} catch (err) {
|
|
31
31
|
error = err
|
|
32
32
|
}
|