nitro-web 0.0.183 → 0.0.185
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/client/app.tsx +3 -3
- package/client/index.ts +1 -0
- package/components/auth/auth.api.js +257 -177
- package/components/auth/inviteConfirm.tsx +106 -0
- package/components/auth/signup.tsx +6 -3
- package/package.json +1 -1
- package/server/constants.js +268 -0
- package/server/index.js +4 -1
- package/server/models/company.js +10 -9
- package/server/models/user.js +7 -6
- package/server/router.js +2 -2
- package/types/components/auth/auth.api.d.ts +41 -39
- package/types/components/auth/auth.api.d.ts.map +1 -1
- package/types/server/constants.d.ts +26 -0
- package/types/server/constants.d.ts.map +1 -0
- package/types/server/index.d.ts +10 -1
- package/types/server/index.d.ts.map +1 -1
- package/types/server/models/company.d.ts +16 -2
- package/types/server/models/company.d.ts.map +1 -1
- package/types/server/models/user.d.ts +19 -38
- package/types/server/models/user.d.ts.map +1 -1
- package/types.ts +1 -2
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Topbar, Field, FormError, Button, request, onChange, getResponseErrors, showError } from 'nitro-web'
|
|
2
|
+
import { Errors } from 'nitro-web/types'
|
|
3
|
+
import { Fragment, useEffect } from 'react'
|
|
4
|
+
|
|
5
|
+
type InviteConfirmProps = {
|
|
6
|
+
className?: string,
|
|
7
|
+
elements?: { Button?: typeof Button },
|
|
8
|
+
redirectTo?: string,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function InviteConfirm({ className, elements, redirectTo }: InviteConfirmProps) {
|
|
12
|
+
const navigate = useNavigate()
|
|
13
|
+
const params = useParams()
|
|
14
|
+
const [store, setStore] = useTracked()
|
|
15
|
+
const [isLoading, setIsLoading] = useState(false)
|
|
16
|
+
const [accepted, setAccepted] = useState(false)
|
|
17
|
+
const [state, setState] = useState(() => ({
|
|
18
|
+
firstName: '',
|
|
19
|
+
lastName: '',
|
|
20
|
+
password: '',
|
|
21
|
+
password2: '',
|
|
22
|
+
token: params.token,
|
|
23
|
+
errors: [] as Errors,
|
|
24
|
+
}))
|
|
25
|
+
|
|
26
|
+
const Elements = {
|
|
27
|
+
Button: elements?.Button || Button,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Auto-confirm on mount for already signed-in users
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (store.user) submit({ token: params.token })
|
|
33
|
+
}, [])
|
|
34
|
+
|
|
35
|
+
async function submit(data: object, event?: React.FormEvent<HTMLFormElement>) {
|
|
36
|
+
try {
|
|
37
|
+
if (isLoading) return
|
|
38
|
+
const result = await request('post /api/invite-confirm', data, event, setIsLoading, setState)
|
|
39
|
+
setStore((s) => ({ ...s, ...result }))
|
|
40
|
+
setAccepted(true)
|
|
41
|
+
setTimeout(() => navigate(redirectTo || '/'), 5000)
|
|
42
|
+
} catch (e) {
|
|
43
|
+
showError(setStore, e)
|
|
44
|
+
setState((s) => ({ ...s, errors: getResponseErrors(e) }))
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (store.user) {
|
|
49
|
+
return (
|
|
50
|
+
<div className={className}>
|
|
51
|
+
<div class="py-12 text-center">
|
|
52
|
+
{accepted ? (
|
|
53
|
+
<Fragment>
|
|
54
|
+
<p class="text-lg font-semibold">Your invite has been accepted.</p>
|
|
55
|
+
<p class="text-sm text-gray-500 mt-1">You'll be redirected back to the <Link to="/">home page</Link> shortly...</p>
|
|
56
|
+
</Fragment>
|
|
57
|
+
) : isLoading ? (
|
|
58
|
+
<Fragment>
|
|
59
|
+
<p class="text-lg font-semibold">Accepting your invite...</p>
|
|
60
|
+
<p class="text-sm text-gray-500 mt-1">Please wait while we confirm your invite.</p>
|
|
61
|
+
</Fragment>
|
|
62
|
+
) : (
|
|
63
|
+
<Fragment>
|
|
64
|
+
<p class="text-lg font-semibold mb-2">Oops! Something went wrong.</p>
|
|
65
|
+
<span class="text-sm text-red-500 bg-red-50 p-1 rounded-md mt-1">{state.errors.map((error) => error.detail).join(', ')}</span>
|
|
66
|
+
</Fragment>
|
|
67
|
+
)}
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<div className={className}>
|
|
75
|
+
<Topbar title={<Fragment>Accept Your Invite</Fragment>} />
|
|
76
|
+
|
|
77
|
+
<form onSubmit={(e) => submit(state, e)} class="mb-0">
|
|
78
|
+
<div class="grid grid-cols-2 gap-6">
|
|
79
|
+
<div>
|
|
80
|
+
<label for="firstName">First Name</label>
|
|
81
|
+
<Field name="firstName" type="text" state={state} onChange={(e) => onChange(e, setState)} placeholder="Your first name..." />
|
|
82
|
+
</div>
|
|
83
|
+
<div>
|
|
84
|
+
<label for="lastName">Last Name</label>
|
|
85
|
+
<Field name="lastName" type="text" state={state} onChange={(e) => onChange(e, setState)} placeholder="Your last name..." />
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
<div>
|
|
89
|
+
<label for="password">Choose a Password</label>
|
|
90
|
+
<Field name="password" type="password" state={state} onChange={(e) => onChange(e, setState)} />
|
|
91
|
+
</div>
|
|
92
|
+
<div>
|
|
93
|
+
<label for="password2">Repeat Your Password</label>
|
|
94
|
+
<Field name="password2" type="password" state={state} onChange={(e) => onChange(e, setState)} />
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<div class="mb-14">
|
|
98
|
+
Already have an account? <Link to="/signin" class="underline2 is-active">Sign in here</Link> first then revisit this link.
|
|
99
|
+
<FormError state={state} className="pt-2" />
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<Elements.Button class="w-full" isLoading={isLoading} type="submit">Accept Invite & Create Account</Elements.Button>
|
|
103
|
+
</form>
|
|
104
|
+
</div>
|
|
105
|
+
)
|
|
106
|
+
}
|
|
@@ -15,7 +15,7 @@ export function Signup({ className, elements, redirectTo }: signupProps) {
|
|
|
15
15
|
const [state, setState] = useState({
|
|
16
16
|
email: injectedConfig.env === 'development' ? (injectedConfig.placeholderEmail || '') : '',
|
|
17
17
|
name: injectedConfig.env === 'development' ? 'Bruce Wayne' : '',
|
|
18
|
-
business: { name: injectedConfig.env === 'development' ? 'Wayne Enterprises' : '' },
|
|
18
|
+
company: { business: { name: injectedConfig.env === 'development' ? 'Wayne Enterprises' : '' } },
|
|
19
19
|
password: injectedConfig.env === 'development' ? '' : '',
|
|
20
20
|
errors: [] as Errors,
|
|
21
21
|
})
|
|
@@ -49,8 +49,11 @@ export function Signup({ className, elements, redirectTo }: signupProps) {
|
|
|
49
49
|
/>
|
|
50
50
|
</div>
|
|
51
51
|
<div>
|
|
52
|
-
<label for="business.name">Company Name</label>
|
|
53
|
-
<Field name="business.name" placeholder="E.g. Wayne Enterprises" state={state}
|
|
52
|
+
<label for="company.business.name">Company Name</label>
|
|
53
|
+
<Field name="company.business.name" placeholder="E.g. Wayne Enterprises" state={state}
|
|
54
|
+
onChange={(e) => onChange(e, setState)}
|
|
55
|
+
errorTitle={/business\.name/}
|
|
56
|
+
/>
|
|
54
57
|
</div>
|
|
55
58
|
</div>
|
|
56
59
|
<div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nitro-web",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.185",
|
|
4
4
|
"repository": "github:boycce/nitro-web",
|
|
5
5
|
"homepage": "https://boycce.github.io/nitro-web/",
|
|
6
6
|
"description": "Nitro is a battle-tested, modular base project to turbocharge your projects, styled using Tailwind 🚀",
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// --- Enums ------------------------------------
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {'af'|'al'|'dz'|'ad'|'ao'|'ag'|'ar'|'am'|'au'|'at'|'az'|'bs'|'bh'|'bd'|'bb'|'by'|'be'|'bz'|'bj'|'bt'|'bo'|'ba'|'bw'|'br'|
|
|
5
|
+
* 'bn'|'bg'|'bf'|'bi'|'cv'|'kh'|'cm'|'ca'|'cf'|'td'|'cl'|'cn'|'co'|'km'|'cg'|'cr'|'hr'|'cu'|'cy'|'cz'|'cd'|'dk'|'dj'|'dm'|'do'|'ec'|
|
|
6
|
+
* 'eg'|'sv'|'gq'|'er'|'ee'|'sz'|'et'|'fj'|'fi'|'fr'|'ga'|'gm'|'ge'|'de'|'gh'|'gr'|'gd'|'gt'|'gn'|'gw'|'gy'|'ht'|'hn'|'hu'|'is'|
|
|
7
|
+
* 'in'|'id'|'ir'|'iq'|'ie'|'il'|'it'|'jm'|'jp'|'jo'|'kz'|'ke'|'ki'|'kw'|'kg'|'la'|'lv'|'lb'|'ls'|'lr'|'ly'|'li'|'lt'|'lu'|'mg'|
|
|
8
|
+
* 'mw'|'my'|'mv'|'ml'|'mt'|'mh'|'mr'|'mu'|'mx'|'fm'|'md'|'mc'|'mn'|'me'|'ma'|'mz'|'mm'|'na'|'nr'|'np'|'nl'|'nz'|'ni'|'ne'|'ng'|
|
|
9
|
+
* 'kp'|'mk'|'no'|'om'|'pk'|'pw'|'pa'|'pg'|'py'|'pe'|'ph'|'pl'|'pt'|'qa'|'ro'|'ru'|'rw'|'kn'|'lc'|'vc'|'ws'|'sm'|'st'|'sa'|'sn'|
|
|
10
|
+
* 'rs'|'sc'|'sl'|'sg'|'sk'|'si'|'sb'|'so'|'za'|'kr'|'ss'|'es'|'lk'|'sd'|'sr'|'se'|'ch'|'sy'|'tj'|'tz'|'th'|'tl'|'tg'|'to'|'tt'|
|
|
11
|
+
* 'tn'|'tr'|'tm'|'tv'|'ug'|'ua'|'ae'|'gb'|'us'|'uy'|'uz'|'vu'|'va'|'ve'|'vn'|'ye'|'zm'|'zw'} Country
|
|
12
|
+
* @typedef {'nzd'|'aud'|'usd'|'gbp'|'btc'|'aed'|'ars'|'bdt'|'bhd'|'brl'|'cad'|'chf'|'clp'|'cny'|'cop'|'czk'|'dkk'|'egp'|'eur'|
|
|
13
|
+
* 'hkd'|'huf'|'idr'|'ils'|'inr'|'jod'|'jpy'|'kes'|'krw'|'kwd'|'lkr'|'mad'|'mxn'|'myr'|'ngn'|'nok'|'omr'|'pen'|'php'|'pkt'|
|
|
14
|
+
* 'pln'|'qar'|'ron'|'rub'|'sar'|'sek'|'sgd'|'thb'|'try'|'twd'|'uah'|'vnd'|'zar'} Currency
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** @type {{ [key in Currency]: { name: string, symbol: string, digits: number } }} */
|
|
18
|
+
export const currencies = {
|
|
19
|
+
nzd: { name: 'New Zealand Dollar', symbol: '$', digits: 2 },
|
|
20
|
+
aud: { name: 'Australian Dollar', symbol: '$', digits: 2 },
|
|
21
|
+
usd: { name: 'US Dollar', symbol: '$', digits: 2 },
|
|
22
|
+
gbp: { name: 'Great Britain Pound', symbol: '£', digits: 2 },
|
|
23
|
+
btc: { name: 'Bitcoin', symbol: '₿', digits: 8 },
|
|
24
|
+
aed: { name: 'UAE Dirham', symbol: 'د.إ', digits: 2 },
|
|
25
|
+
ars: { name: 'Argentine Peso', symbol: '$', digits: 2 },
|
|
26
|
+
bdt: { name: 'Bangladeshi Taka', symbol: '৳', digits: 2 },
|
|
27
|
+
bhd: { name: 'Bahraini Dinar', symbol: '.د.ب', digits: 3 },
|
|
28
|
+
brl: { name: 'Brazilian Real', symbol: 'R$', digits: 2 },
|
|
29
|
+
cad: { name: 'Canadian Dollar', symbol: '$', digits: 2 },
|
|
30
|
+
chf: { name: 'Swiss Franc', symbol: 'Fr', digits: 2 },
|
|
31
|
+
clp: { name: 'Chilean Peso', symbol: '$', digits: 0 },
|
|
32
|
+
cny: { name: 'Chinese Yuan', symbol: '¥', digits: 2 },
|
|
33
|
+
cop: { name: 'Colombian Peso', symbol: '$', digits: 2 },
|
|
34
|
+
czk: { name: 'Czech Koruna', symbol: 'Kč', digits: 2 },
|
|
35
|
+
dkk: { name: 'Danish Krone', symbol: 'kr', digits: 2 },
|
|
36
|
+
egp: { name: 'Egyptian Pound', symbol: '£', digits: 2 },
|
|
37
|
+
eur: { name: 'Euro', symbol: '€', digits: 2 },
|
|
38
|
+
hkd: { name: 'Hong Kong Dollar', symbol: '$', digits: 2 },
|
|
39
|
+
huf: { name: 'Hungarian Forint', symbol: 'Ft', digits: 0 },
|
|
40
|
+
idr: { name: 'Indonesian Rupiah', symbol: 'Rp', digits: 0 },
|
|
41
|
+
ils: { name: 'Israeli Shekel', symbol: '₪', digits: 2 },
|
|
42
|
+
inr: { name: 'Indian Rupee', symbol: '₹', digits: 2 },
|
|
43
|
+
jod: { name: 'Jordanian Dinar', symbol: 'د.ا', digits: 3 },
|
|
44
|
+
jpy: { name: 'Japanese Yen', symbol: '¥', digits: 0 },
|
|
45
|
+
kes: { name: 'Kenyan Shilling', symbol: 'Sh', digits: 2 },
|
|
46
|
+
krw: { name: 'South Korean Won', symbol: '₩', digits: 0 },
|
|
47
|
+
kwd: { name: 'Kuwaiti Dinar', symbol: 'د.ك', digits: 3 },
|
|
48
|
+
lkr: { name: 'Sri Lankan Rupee', symbol: 'Rs', digits: 2 },
|
|
49
|
+
mad: { name: 'Moroccan Dirham', symbol: 'د.م.', digits: 2 },
|
|
50
|
+
mxn: { name: 'Mexican Peso', symbol: '$', digits: 2 },
|
|
51
|
+
myr: { name: 'Malaysian Ringgit', symbol: 'RM', digits: 2 },
|
|
52
|
+
ngn: { name: 'Nigerian Naira', symbol: '₦', digits: 2 },
|
|
53
|
+
nok: { name: 'Norwegian Krone', symbol: 'kr', digits: 2 },
|
|
54
|
+
omr: { name: 'Omani Rial', symbol: '﷼', digits: 3 },
|
|
55
|
+
pen: { name: 'Peruvian Sol', symbol: 'S/', digits: 2 },
|
|
56
|
+
php: { name: 'Philippine Peso', symbol: '₱', digits: 2 },
|
|
57
|
+
pkt: { name: 'Pakistani Rupee', symbol: '₨', digits: 2 },
|
|
58
|
+
pln: { name: 'Polish Zloty', symbol: 'zł', digits: 2 },
|
|
59
|
+
qar: { name: 'Qatari Riyal', symbol: '﷼', digits: 2 },
|
|
60
|
+
ron: { name: 'Romanian Leu', symbol: 'lei', digits: 2 },
|
|
61
|
+
rub: { name: 'Russian Ruble', symbol: '₽', digits: 2 },
|
|
62
|
+
sar: { name: 'Saudi Riyal', symbol: '﷼', digits: 2 },
|
|
63
|
+
sek: { name: 'Swedish Krona', symbol: 'kr', digits: 2 },
|
|
64
|
+
sgd: { name: 'Singapore Dollar', symbol: '$', digits: 2 },
|
|
65
|
+
thb: { name: 'Thai Baht', symbol: '฿', digits: 2 },
|
|
66
|
+
try: { name: 'Turkish Lira', symbol: '₺', digits: 2 },
|
|
67
|
+
twd: { name: 'New Taiwan Dollar', symbol: 'NT$', digits: 2 },
|
|
68
|
+
uah: { name: 'Ukrainian Hryvnia', symbol: '₴', digits: 2 },
|
|
69
|
+
vnd: { name: 'Vietnamese Dong', symbol: '₫', digits: 0 },
|
|
70
|
+
zar: { name: 'South African Rand', symbol: 'R', digits: 2 },
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** @type {{ [key in Country]: { name: string } }} */
|
|
74
|
+
export const countries = {
|
|
75
|
+
af: { name: 'Afghanistan' },
|
|
76
|
+
al: { name: 'Albania' },
|
|
77
|
+
dz: { name: 'Algeria' },
|
|
78
|
+
ad: { name: 'Andorra' },
|
|
79
|
+
ao: { name: 'Angola' },
|
|
80
|
+
ag: { name: 'Antigua and Barbuda' },
|
|
81
|
+
ar: { name: 'Argentina' },
|
|
82
|
+
am: { name: 'Armenia' },
|
|
83
|
+
au: { name: 'Australia' },
|
|
84
|
+
at: { name: 'Austria' },
|
|
85
|
+
az: { name: 'Azerbaijan' },
|
|
86
|
+
bs: { name: 'Bahamas' },
|
|
87
|
+
bh: { name: 'Bahrain' },
|
|
88
|
+
bd: { name: 'Bangladesh' },
|
|
89
|
+
bb: { name: 'Barbados' },
|
|
90
|
+
by: { name: 'Belarus' },
|
|
91
|
+
be: { name: 'Belgium' },
|
|
92
|
+
bz: { name: 'Belize' },
|
|
93
|
+
bj: { name: 'Benin' },
|
|
94
|
+
bt: { name: 'Bhutan' },
|
|
95
|
+
bo: { name: 'Bolivia' },
|
|
96
|
+
ba: { name: 'Bosnia and Herzegovina' },
|
|
97
|
+
bw: { name: 'Botswana' },
|
|
98
|
+
br: { name: 'Brazil' },
|
|
99
|
+
bn: { name: 'Brunei' },
|
|
100
|
+
bg: { name: 'Bulgaria' },
|
|
101
|
+
bf: { name: 'Burkina Faso' },
|
|
102
|
+
bi: { name: 'Burundi' },
|
|
103
|
+
cv: { name: 'Cabo Verde' },
|
|
104
|
+
kh: { name: 'Cambodia' },
|
|
105
|
+
cm: { name: 'Cameroon' },
|
|
106
|
+
ca: { name: 'Canada' },
|
|
107
|
+
cf: { name: 'Central African Republic' },
|
|
108
|
+
td: { name: 'Chad' },
|
|
109
|
+
cl: { name: 'Chile' },
|
|
110
|
+
cn: { name: 'China' },
|
|
111
|
+
co: { name: 'Colombia' },
|
|
112
|
+
km: { name: 'Comoros' },
|
|
113
|
+
cg: { name: 'Congo (Congo-Brazzaville)' },
|
|
114
|
+
cr: { name: 'Costa Rica' },
|
|
115
|
+
hr: { name: 'Croatia' },
|
|
116
|
+
cu: { name: 'Cuba' },
|
|
117
|
+
cy: { name: 'Cyprus' },
|
|
118
|
+
cz: { name: 'Czechia' },
|
|
119
|
+
cd: { name: 'Democratic Republic of the Congo' },
|
|
120
|
+
dk: { name: 'Denmark' },
|
|
121
|
+
dj: { name: 'Djibouti' },
|
|
122
|
+
dm: { name: 'Dominica' },
|
|
123
|
+
do: { name: 'Dominican Republic' },
|
|
124
|
+
ec: { name: 'Ecuador' },
|
|
125
|
+
eg: { name: 'Egypt' },
|
|
126
|
+
sv: { name: 'El Salvador' },
|
|
127
|
+
gq: { name: 'Equatorial Guinea' },
|
|
128
|
+
er: { name: 'Eritrea' },
|
|
129
|
+
ee: { name: 'Estonia' },
|
|
130
|
+
sz: { name: 'Eswatini' },
|
|
131
|
+
et: { name: 'Ethiopia' },
|
|
132
|
+
fj: { name: 'Fiji' },
|
|
133
|
+
fi: { name: 'Finland' },
|
|
134
|
+
fr: { name: 'France' },
|
|
135
|
+
ga: { name: 'Gabon' },
|
|
136
|
+
gm: { name: 'Gambia' },
|
|
137
|
+
ge: { name: 'Georgia' },
|
|
138
|
+
de: { name: 'Germany' },
|
|
139
|
+
gh: { name: 'Ghana' },
|
|
140
|
+
gr: { name: 'Greece' },
|
|
141
|
+
gd: { name: 'Grenada' },
|
|
142
|
+
gt: { name: 'Guatemala' },
|
|
143
|
+
gn: { name: 'Guinea' },
|
|
144
|
+
gw: { name: 'Guinea-Bissau' },
|
|
145
|
+
gy: { name: 'Guyana' },
|
|
146
|
+
ht: { name: 'Haiti' },
|
|
147
|
+
hn: { name: 'Honduras' },
|
|
148
|
+
hu: { name: 'Hungary' },
|
|
149
|
+
is: { name: 'Iceland' },
|
|
150
|
+
in: { name: 'India' },
|
|
151
|
+
id: { name: 'Indonesia' },
|
|
152
|
+
ir: { name: 'Iran' },
|
|
153
|
+
iq: { name: 'Iraq' },
|
|
154
|
+
ie: { name: 'Ireland' },
|
|
155
|
+
il: { name: 'Israel' },
|
|
156
|
+
it: { name: 'Italy' },
|
|
157
|
+
jm: { name: 'Jamaica' },
|
|
158
|
+
jp: { name: 'Japan' },
|
|
159
|
+
jo: { name: 'Jordan' },
|
|
160
|
+
kz: { name: 'Kazakhstan' },
|
|
161
|
+
ke: { name: 'Kenya' },
|
|
162
|
+
ki: { name: 'Kiribati' },
|
|
163
|
+
kw: { name: 'Kuwait' },
|
|
164
|
+
kg: { name: 'Kyrgyzstan' },
|
|
165
|
+
la: { name: 'Laos' },
|
|
166
|
+
lv: { name: 'Latvia' },
|
|
167
|
+
lb: { name: 'Lebanon' },
|
|
168
|
+
ls: { name: 'Lesotho' },
|
|
169
|
+
lr: { name: 'Liberia' },
|
|
170
|
+
ly: { name: 'Libya' },
|
|
171
|
+
li: { name: 'Liechtenstein' },
|
|
172
|
+
lt: { name: 'Lithuania' },
|
|
173
|
+
lu: { name: 'Luxembourg' },
|
|
174
|
+
mg: { name: 'Madagascar' },
|
|
175
|
+
mw: { name: 'Malawi' },
|
|
176
|
+
my: { name: 'Malaysia' },
|
|
177
|
+
mv: { name: 'Maldives' },
|
|
178
|
+
ml: { name: 'Mali' },
|
|
179
|
+
mt: { name: 'Malta' },
|
|
180
|
+
mh: { name: 'Marshall Islands' },
|
|
181
|
+
mr: { name: 'Mauritania' },
|
|
182
|
+
mu: { name: 'Mauritius' },
|
|
183
|
+
mx: { name: 'Mexico' },
|
|
184
|
+
fm: { name: 'Micronesia' },
|
|
185
|
+
md: { name: 'Moldova' },
|
|
186
|
+
mc: { name: 'Monaco' },
|
|
187
|
+
mn: { name: 'Mongolia' },
|
|
188
|
+
me: { name: 'Montenegro' },
|
|
189
|
+
ma: { name: 'Morocco' },
|
|
190
|
+
mz: { name: 'Mozambique' },
|
|
191
|
+
mm: { name: 'Myanmar' },
|
|
192
|
+
na: { name: 'Namibia' },
|
|
193
|
+
nr: { name: 'Nauru' },
|
|
194
|
+
np: { name: 'Nepal' },
|
|
195
|
+
nl: { name: 'Netherlands' },
|
|
196
|
+
nz: { name: 'New Zealand' },
|
|
197
|
+
ni: { name: 'Nicaragua' },
|
|
198
|
+
ne: { name: 'Niger' },
|
|
199
|
+
ng: { name: 'Nigeria' },
|
|
200
|
+
kp: { name: 'North Korea' },
|
|
201
|
+
mk: { name: 'North Macedonia' },
|
|
202
|
+
no: { name: 'Norway' },
|
|
203
|
+
om: { name: 'Oman' },
|
|
204
|
+
pk: { name: 'Pakistan' },
|
|
205
|
+
pw: { name: 'Palau' },
|
|
206
|
+
pa: { name: 'Panama' },
|
|
207
|
+
pg: { name: 'Papua New Guinea' },
|
|
208
|
+
py: { name: 'Paraguay' },
|
|
209
|
+
pe: { name: 'Peru' },
|
|
210
|
+
ph: { name: 'Philippines' },
|
|
211
|
+
pl: { name: 'Poland' },
|
|
212
|
+
pt: { name: 'Portugal' },
|
|
213
|
+
qa: { name: 'Qatar' },
|
|
214
|
+
ro: { name: 'Romania' },
|
|
215
|
+
ru: { name: 'Russia' },
|
|
216
|
+
rw: { name: 'Rwanda' },
|
|
217
|
+
kn: { name: 'Saint Kitts and Nevis' },
|
|
218
|
+
lc: { name: 'Saint Lucia' },
|
|
219
|
+
vc: { name: 'Saint Vincent and the Grenadines' },
|
|
220
|
+
ws: { name: 'Samoa' },
|
|
221
|
+
sm: { name: 'San Marino' },
|
|
222
|
+
st: { name: 'Sao Tome and Principe' },
|
|
223
|
+
sa: { name: 'Saudi Arabia' },
|
|
224
|
+
sn: { name: 'Senegal' },
|
|
225
|
+
rs: { name: 'Serbia' },
|
|
226
|
+
sc: { name: 'Seychelles' },
|
|
227
|
+
sl: { name: 'Sierra Leone' },
|
|
228
|
+
sg: { name: 'Singapore' },
|
|
229
|
+
sk: { name: 'Slovakia' },
|
|
230
|
+
si: { name: 'Slovenia' },
|
|
231
|
+
sb: { name: 'Solomon Islands' },
|
|
232
|
+
so: { name: 'Somalia' },
|
|
233
|
+
za: { name: 'South Africa' },
|
|
234
|
+
kr: { name: 'South Korea' },
|
|
235
|
+
ss: { name: 'South Sudan' },
|
|
236
|
+
es: { name: 'Spain' },
|
|
237
|
+
lk: { name: 'Sri Lanka' },
|
|
238
|
+
sd: { name: 'Sudan' },
|
|
239
|
+
sr: { name: 'Suriname' },
|
|
240
|
+
se: { name: 'Sweden' },
|
|
241
|
+
ch: { name: 'Switzerland' },
|
|
242
|
+
sy: { name: 'Syria' },
|
|
243
|
+
tj: { name: 'Tajikistan' },
|
|
244
|
+
tz: { name: 'Tanzania' },
|
|
245
|
+
th: { name: 'Thailand' },
|
|
246
|
+
tl: { name: 'Timor-Leste' },
|
|
247
|
+
tg: { name: 'Togo' },
|
|
248
|
+
to: { name: 'Tonga' },
|
|
249
|
+
tt: { name: 'Trinidad and Tobago' },
|
|
250
|
+
tn: { name: 'Tunisia' },
|
|
251
|
+
tr: { name: 'Turkey' },
|
|
252
|
+
tm: { name: 'Turkmenistan' },
|
|
253
|
+
tv: { name: 'Tuvalu' },
|
|
254
|
+
ug: { name: 'Uganda' },
|
|
255
|
+
ua: { name: 'Ukraine' },
|
|
256
|
+
ae: { name: 'United Arab Emirates' },
|
|
257
|
+
gb: { name: 'United Kingdom' },
|
|
258
|
+
us: { name: 'United States' },
|
|
259
|
+
uy: { name: 'Uruguay' },
|
|
260
|
+
uz: { name: 'Uzbekistan' },
|
|
261
|
+
vu: { name: 'Vanuatu' },
|
|
262
|
+
va: { name: 'Vatican City' },
|
|
263
|
+
ve: { name: 'Venezuela' },
|
|
264
|
+
vn: { name: 'Vietnam' },
|
|
265
|
+
ye: { name: 'Yemen' },
|
|
266
|
+
zm: { name: 'Zambia' },
|
|
267
|
+
zw: { name: 'Zimbabwe' },
|
|
268
|
+
}
|
package/server/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
export * from '../util.js'
|
|
3
3
|
export * as util from '../util.js'
|
|
4
|
+
export { currencies, countries } from './constants.js'
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* Re-export
|
|
7
|
+
* Re-export types from nitro-web/server
|
|
7
8
|
* @typedef {import('./router.js').MiddlewareConfig} MiddlewareConfig
|
|
9
|
+
* @typedef {import('./constants.js').Country} Country
|
|
10
|
+
* @typedef {import('./constants.js').Currency} Currency
|
|
8
11
|
*/
|
|
9
12
|
|
|
10
13
|
// Export models
|
package/server/models/company.js
CHANGED
|
@@ -13,17 +13,20 @@ export default {
|
|
|
13
13
|
phone: { type: 'string' },
|
|
14
14
|
website: { type: 'string', isURL: true },
|
|
15
15
|
},
|
|
16
|
-
status: { type: 'string', default: 'active', enum: ['active', 'unpaid', 'deleted'] },
|
|
16
|
+
status: { type: 'string', default: 'active', enum: ['active', 'unpaid', 'deleted'], required: true },
|
|
17
17
|
users: [{
|
|
18
|
-
_id: { model: 'user' },
|
|
19
|
-
role: { type: 'string', enum: ['owner', 'manager',
|
|
20
|
-
status: { type: 'string',
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
_id: { model: 'user', required: true },
|
|
19
|
+
role: { type: 'string', enum: ['owner', 'manager'], required: true },
|
|
20
|
+
status: { type: 'string', default: 'active', enum: ['active', 'deleted'], required: true },
|
|
21
|
+
}],
|
|
22
|
+
invites: [{
|
|
23
|
+
email: { type: 'email', required: true },
|
|
24
|
+
role: { type: 'string', enum: ['owner', 'manager'], required: true },
|
|
25
|
+
inviteToken: { type: 'string', required: true },
|
|
23
26
|
}],
|
|
24
27
|
},
|
|
25
28
|
|
|
26
|
-
findBL: ['
|
|
29
|
+
findBL: ['invites.token'],
|
|
27
30
|
updateBL: ['status', 'users'],
|
|
28
31
|
|
|
29
32
|
afterFind: [
|
|
@@ -34,8 +37,6 @@ export default {
|
|
|
34
37
|
for (let i=data.users.length; i--;) {
|
|
35
38
|
const user = data.users[i]
|
|
36
39
|
const userExpanded = data.usersExpanded.find(o => String(o._id) == String(user._id))
|
|
37
|
-
// console.log(userExpanded)
|
|
38
|
-
if (user.inviteEmail) user.email = user.inviteEmail
|
|
39
40
|
if (userExpanded) Object.assign(user, { ...userExpanded, name: fullName(userExpanded) })
|
|
40
41
|
}
|
|
41
42
|
delete data.usersExpanded
|
package/server/models/user.js
CHANGED
|
@@ -5,25 +5,26 @@ export default {
|
|
|
5
5
|
|
|
6
6
|
fields: {
|
|
7
7
|
avatar: { type: 'image' },
|
|
8
|
-
company: { model: 'company', required: true },
|
|
8
|
+
company: { model: 'company', required: true }, // AKA "active company"
|
|
9
9
|
email: { type: 'email', required: true, index: 'unique' },
|
|
10
|
-
|
|
10
|
+
isAdmin: { type: 'boolean', default: false },
|
|
11
11
|
firstName: { type: 'string', required: true },
|
|
12
12
|
lastName: { type: 'string', required: true },
|
|
13
|
-
status: { type: 'string', default: 'active', enum: ['active', 'deleted', 'inactive'] },
|
|
14
13
|
stripeCustomer: { type: 'any' },
|
|
15
14
|
stripeSubscription: { type: 'any' },
|
|
16
15
|
stripeIntents: { type: 'any' },
|
|
17
|
-
type: { type: 'string', default: 'user', enum: ['user', 'admin'] },
|
|
18
16
|
usedFreeTrial: { type: 'boolean', default: false },
|
|
19
17
|
// hidden fields
|
|
20
18
|
password: { type: 'string', minLength: 6 },
|
|
21
|
-
inviteToken: { type: 'string' },
|
|
22
19
|
resetToken: { type: 'string' },
|
|
20
|
+
// If single tenancy application
|
|
21
|
+
// status: { type: 'string', default: 'active', enum: ['active', 'deleted'] },
|
|
22
|
+
// isInvited: { type: 'boolean' }
|
|
23
|
+
// inviteToken: { type: 'string' },
|
|
23
24
|
},
|
|
24
25
|
|
|
25
26
|
findBL: ['password', 'inviteToken', 'resetToken'],
|
|
26
|
-
updateBL: ['password', 'inviteToken', 'resetToken', 'company', 'status', 'stripeSubscription', '
|
|
27
|
+
updateBL: ['password', 'inviteToken', 'resetToken', 'company', 'status', 'stripeSubscription', 'isAdmin', 'usedFreeTrial'],
|
|
27
28
|
|
|
28
29
|
messages: {
|
|
29
30
|
lastName: {
|
package/server/router.js
CHANGED
|
@@ -404,7 +404,7 @@ export const middleware = {
|
|
|
404
404
|
}
|
|
405
405
|
|
|
406
406
|
export function isAdminUser(req) {
|
|
407
|
-
return
|
|
407
|
+
return req.user?.isAdmin ? true : false
|
|
408
408
|
}
|
|
409
409
|
|
|
410
410
|
export function isValidUserOrRespond(req, res) {
|
|
@@ -424,7 +424,7 @@ export function isValidUserOrRespond(req, res) {
|
|
|
424
424
|
function isValidParamCompanyUserOrRespond(req, res, checkIsOwner = false) {
|
|
425
425
|
const _company = req.user?.company?._id?.toString() == req.params.cid ? req.user.company : false
|
|
426
426
|
const company = _company || req.user?.companies?.find((o) => o._id.toString() == req.params.cid)
|
|
427
|
-
const isCompanyOwner = company?.users?.find((o) => o._id.toString() == req.user?._id?.toString() && o.
|
|
427
|
+
const isCompanyOwner = company?.users?.find((o) => o._id.toString() == req.user?._id?.toString() && o.role === 'owner')
|
|
428
428
|
if (!isValidUserOrRespond(req, res)) return
|
|
429
429
|
else if (!isAdminUser(req) && !company) res.unauthorized('You are not authorised to make this request.')
|
|
430
430
|
else if (!isAdminUser(req) && checkIsOwner && !isCompanyOwner) res.unauthorized('Only owners can make this request.')
|
|
@@ -1,37 +1,48 @@
|
|
|
1
|
-
export function findUserFromProvider(query: any, passwordToCheck: any, ...args: any[]): Promise<any>;
|
|
2
|
-
export function getStore(user: any): Promise<{
|
|
3
|
-
user: any;
|
|
4
|
-
}>;
|
|
5
|
-
export function signinAndGetStore(user: any, isDesktop: any, getStore: any): Promise<any>;
|
|
6
|
-
export function userCreate({ business, password, ...userDataProp }: {
|
|
7
|
-
[x: string]: any;
|
|
8
|
-
business: any;
|
|
9
|
-
password: any;
|
|
10
|
-
}): Promise<any>;
|
|
11
|
-
export function tokenCreate(id: any): Promise<any>;
|
|
12
|
-
export function tokenParse(token: any): any;
|
|
13
|
-
export function validatePassword(password: string, password2: any): Promise<void>;
|
|
14
1
|
export function resetInstructions(req: any, res: any): Promise<void>;
|
|
15
2
|
export function inviteInstructions(req: any, res: any): Promise<void>;
|
|
16
|
-
export function inviteConfirm(req: any, res: any): Promise<void>;
|
|
17
3
|
export function resetConfirm(req: any, res: any): Promise<void>;
|
|
18
|
-
export function
|
|
4
|
+
export function inviteConfirm(req: any, res: any): Promise<void>;
|
|
5
|
+
export function userFindFromProvider(query: any, passwordToCheck: any, ...args: any[]): Promise<any>;
|
|
6
|
+
export function userSigninGetStore(user: any, isDesktop: any): Promise<any>;
|
|
7
|
+
export function getStore(user: any): Promise<{
|
|
8
|
+
user: any;
|
|
9
|
+
}>;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new user and company (if multi tenant and `user.company` is not an id)
|
|
12
|
+
* @param {object} userData - user data
|
|
13
|
+
* @param {string} [userData.password] - optional
|
|
14
|
+
* @param {string} [userData.password2] - optional, to confirm the password
|
|
15
|
+
* @param {string} [userData.company] - if multi tenant and `user.company` is not an id, create a new company
|
|
16
|
+
* @param {boolean} [skipSendEmail=false] - whether to skip sending the welcome email
|
|
17
|
+
* @returns {Promise<object>} - the created user
|
|
18
|
+
*/
|
|
19
|
+
export function userCreate({ password, password2, company, ...userDataProp }: {
|
|
20
|
+
password?: string;
|
|
21
|
+
password2?: string;
|
|
22
|
+
company?: string;
|
|
23
|
+
}, skipSendEmail?: boolean): Promise<object>;
|
|
24
|
+
export function passwordValidate(password: string, password2: any): Promise<void>;
|
|
25
|
+
export function tokenCreate(modelName: any, id: any): Promise<any>;
|
|
26
|
+
export function tokenParse(token: any, modelName: any, maxAgeMs?: number): any;
|
|
27
|
+
export function tokenConfirmForReset(req: any): Promise<any>;
|
|
28
|
+
export function tokenConfirmForSingleTenant(req: any, isReset: any): Promise<any>;
|
|
29
|
+
export function tokenConfirmForMultiTenant(req: any): Promise<any>;
|
|
19
30
|
/**
|
|
20
|
-
*
|
|
31
|
+
* Creates and sends a reset or invite token to a user or company
|
|
21
32
|
* @param {object} options
|
|
22
|
-
* @param {'reset' | 'invite'} options.type -
|
|
23
|
-
* @param {
|
|
24
|
-
* @param {
|
|
25
|
-
* @param {
|
|
33
|
+
* @param {'reset' | 'invite' | 'companyInvite'} options.type - token type (default: 'reset')
|
|
34
|
+
* @param {string} options._id - user or company id
|
|
35
|
+
* @param {string} options.email - recipient email
|
|
36
|
+
* @param {string} options.firstName - recipient first name
|
|
37
|
+
* @param {function} [options.beforeUpdate] - runs before updating the model with the token, return null to skip update
|
|
38
|
+
* @param {function} [options.beforeSendEmail] - runs before sending the email, receives (options, token)
|
|
26
39
|
* @returns {Promise<{token: string, mailgunPromise: Promise<unknown>}>}
|
|
27
40
|
*/
|
|
28
|
-
export function
|
|
29
|
-
type: "reset" | "invite";
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
firstName: string;
|
|
34
|
-
};
|
|
41
|
+
export function tokenSend({ type, _id, email, firstName, beforeUpdate, beforeSendEmail }: {
|
|
42
|
+
type: "reset" | "invite" | "companyInvite";
|
|
43
|
+
_id: string;
|
|
44
|
+
email: string;
|
|
45
|
+
firstName: string;
|
|
35
46
|
beforeUpdate?: Function;
|
|
36
47
|
beforeSendEmail?: Function;
|
|
37
48
|
}): Promise<{
|
|
@@ -44,26 +55,17 @@ export const routes: {
|
|
|
44
55
|
'post /api/signin': (typeof signin)[];
|
|
45
56
|
'post /api/signup': (typeof signup)[];
|
|
46
57
|
'post /api/reset-instructions': (typeof resetInstructions)[];
|
|
47
|
-
'post /api/reset-
|
|
58
|
+
'post /api/reset-confirm': (typeof resetConfirm)[];
|
|
48
59
|
'post /api/invite-instructions': (typeof inviteInstructions)[];
|
|
49
|
-
'post /api/invite-
|
|
60
|
+
'post /api/invite-confirm': (typeof inviteConfirm)[];
|
|
50
61
|
'delete /api/account/:uid': (typeof remove)[];
|
|
51
62
|
setup: typeof setup;
|
|
52
|
-
findUserFromProvider: typeof findUserFromProvider;
|
|
53
|
-
getStore: typeof getStore;
|
|
54
|
-
signinAndGetStore: typeof signinAndGetStore;
|
|
55
|
-
tokenCreate: typeof tokenCreate;
|
|
56
|
-
tokenParse: typeof tokenParse;
|
|
57
|
-
userCreate: typeof userCreate;
|
|
58
|
-
validatePassword: typeof validatePassword;
|
|
59
|
-
sendToken: typeof sendToken;
|
|
60
|
-
inviteOrResetConfirm: typeof inviteOrResetConfirm;
|
|
61
63
|
};
|
|
62
64
|
declare function store(req: any, res: any): Promise<void>;
|
|
63
65
|
declare function signout(req: any, res: any): void;
|
|
64
66
|
declare function signin(req: any, res: any): any;
|
|
65
67
|
declare function signup(req: any, res: any): Promise<void>;
|
|
66
68
|
declare function remove(req: any, res: any): Promise<void>;
|
|
67
|
-
declare function setup(middleware: any, _config: any): void;
|
|
69
|
+
declare function setup(middleware: any, _config: any, helpers?: {}): void;
|
|
68
70
|
export {};
|
|
69
71
|
//# sourceMappingURL=auth.api.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.api.d.ts","sourceRoot":"","sources":["../../../components/auth/auth.api.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.api.d.ts","sourceRoot":"","sources":["../../../components/auth/auth.api.js"],"names":[],"mappings":"AAuKA,qEAeC;AAED,sEAsCC;AAED,gEAMC;AAED,iEAgBC;AAID,qGA8CC;AAED,4EAOC;AAED;;GAKC;AAID;;;;;;;;GAQG;AACH,8EANG;IAA0B,QAAQ,GAA1B,MAAM;IACY,SAAS,GAA3B,MAAM;IACY,OAAO,GAAzB,MAAM;CACd,kBAAQ,OAAO,GACL,OAAO,CAAC,MAAM,CAAC,CA0D3B;AAED,kFAiBC;AAED,mEAOC;AAED,+EAWC;AAED,6DAEC;AAED,kFAoBC;AAED,mEA4BC;AAED;;;;;;;;;;GAUG;AACH,0FARG;IAAsD,IAAI,EAAlD,OAAO,GAAG,QAAQ,GAAG,eAAe;IACpB,GAAG,EAAnB,MAAM;IACU,KAAK,EAArB,MAAM;IACU,SAAS,EAAzB,MAAM;IACa,YAAY;IACZ,eAAe;CAC1C,GAAU,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAC,CAAC,CAuCtE;AA9fD;;;;;;;;;;;EAaC;AAyED,0DAEC;AA6BD,mDAEC;AAnBD,iDAeC;AAzBD,2DAQC;AAuBD,2DAwBC;AAlID,0EAqEC"}
|