nitro-web 0.0.82 → 0.0.84

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 CHANGED
@@ -291,9 +291,9 @@ async function beforeApp(config: Config) {
291
291
 
292
292
  const defaultMiddleware = {
293
293
  // Global middleware that can referenced from component routes
294
- isAdmin: (route: unknown, store: { user?: { type?: string } }) => {
294
+ isAdmin: (route: unknown, store: { user?: { type?: string, isAdmin?: boolean } }) => {
295
295
  const user = store.user || { type: 'visitor' }
296
- if (user?.type?.match(/admin/)) return
296
+ if (user?.type?.match(/admin/) || user?.isAdmin) return
297
297
  else if (user?.type && user?.type !== 'visitor') return { redirect: '/signin?unauth' }
298
298
  else return { redirect: '/signin?signin' }
299
299
  },
@@ -192,7 +192,7 @@ async function resetPassword(req, res) {
192
192
  async function inviteInstructions(req, res) {
193
193
  try {
194
194
  // Check if user is admin here rather than in middleware (which may not exist yet)
195
- if (req.user.type != 'admin') {
195
+ if (req.user.type != 'admin' && !req.user.isAdmin) {
196
196
  throw new Error('You are not authorized to invite users.')
197
197
  }
198
198
  const inviteToken = await tokenCreate()
@@ -158,7 +158,7 @@ export const Filters = forwardRef<FiltersHandleType, FiltersProps>(({
158
158
  <Elements.Field
159
159
  {...filter}
160
160
  class="!mb-0"
161
- value={state[filter.name] as string || ''}
161
+ value={(state[filter.name] as string) || ''}
162
162
  onChange={onInputChange}
163
163
  />
164
164
  }
@@ -37,7 +37,7 @@ export function Drop({ awsUrl, className, id, name, onChange, multiple, state, .
37
37
  stateRef.current = state
38
38
 
39
39
  // Input is always controlled if state is passed in
40
- if (props.value) value = props.value as Image
40
+ if (typeof props.value !== 'undefined') value = props.value as Image
41
41
  else if (typeof state == 'object') value = deepFind(state, name) as Image
42
42
  if (typeof value == 'undefined') value = null
43
43
 
@@ -68,7 +68,7 @@ function FieldBase({ state, icon, iconPos: ip, ...props }: FieldProps) {
68
68
  })
69
69
 
70
70
  // Value: Input is always controlled if state is passed in
71
- if (props.value) value = props.value as string
71
+ if (typeof props.value !== 'undefined') value = props.value as string
72
72
  else if (typeof state == 'object') {
73
73
  const v = deepFind(state, props.name) as string | undefined
74
74
  value = v ?? ''
@@ -57,7 +57,7 @@ function SelectBase({ id, containerId, minMenuWidth, name, prefix='', onChange,
57
57
  if (!name) throw new Error('Select component requires a `name` and `options` prop')
58
58
 
59
59
  // Get value from value or state
60
- if ('value' in props) value = props.value
60
+ if (typeof props.value !== 'undefined') value = props.value
61
61
  else if (typeof state == 'object') value = deepFind(state, name)
62
62
 
63
63
  // If multi-select, filter options by value
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nitro-web",
3
- "version": "0.0.82",
3
+ "version": "0.0.84",
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 🚀",
package/server/router.js CHANGED
@@ -298,8 +298,8 @@ function resolveMiddleware (controllers, middleware, route, item) {
298
298
  }
299
299
 
300
300
  export const middleware = {
301
+ // Default middleware called before all /api/* routes
301
302
  order: [
302
- // Express middleware runtime order that are called for all API requests
303
303
  'loadAssets',
304
304
  'modifyRequest',
305
305
  'parseUrlEncoded',
@@ -308,6 +308,8 @@ export const middleware = {
308
308
  'beforeAPIRoute',
309
309
  ],
310
310
 
311
+ // --- Default middleware ---------------------
312
+
311
313
  modifyRequest: (req, res, next) => {
312
314
  // Handy boolean denoting that the request wants JSON returned
313
315
  // global.start = new Date().getTime()
@@ -345,4 +347,42 @@ export const middleware = {
345
347
  res.set('version', req.version)
346
348
  next()
347
349
  },
350
+
351
+ // --- Custom middleware ----------------------
352
+
353
+ isAdmin: (req, res, next) => {
354
+ // Still need to remove cookie matching in favour of uid..
355
+ // E.g. Cookie matching handy for rare issues, e.g. signout > signin (to a different user on another tab)
356
+ const user = req.user
357
+ let cookieMatch = user && (!req.headers.authid || user._id.toString() == req.headers.authid)
358
+ if (cookieMatch && (user.type?.match(/admin/) || user.isAdmin)) next()
359
+ else if (user && (user.type?.match(/admin/) || user.isAdmin)) res.unauthorized('Invalid cookie, please refresh your browser')
360
+ else if (user) res.unauthorized('You are not authorised to make this request.')
361
+ else res.unauthorized('Please sign in first.')
362
+ },
363
+ isCompanyOwner: (req, res, next) => {
364
+ let user = req.user || { companies: [] }
365
+ let cid = req.params.cid
366
+ let company = user.companies.find((o) => o._id.toString() == cid)
367
+ let companyUser = company?.users?.find((o) => o._id.toString() == user._id.toString())
368
+ if (!user._id) return res.unauthorized('Please sign in first.')
369
+ else if (!company || !companyUser) res.unauthorized('You are not authorised to make this request.')
370
+ else if (companyUser.type != 'owner') res.unauthorized('Only owners can make this request.')
371
+ else next()
372
+ },
373
+ isCompanyUser: (req, res, next) => {
374
+ let user = req.user || { companies: [] }
375
+ let cid = req.params.cid
376
+ let company = user.companies.find((o) => o._id.toString() == cid)
377
+ if (!user._id) return res.unauthorized('Please sign in first.')
378
+ else if (!company) res.unauthorized('You are not authorised to make this request.')
379
+ else next()
380
+ },
381
+ isUser: (req, res, next) => {
382
+ // todo: need to double check that uid is always defined
383
+ let uid = req.params.uid
384
+ if (req.user && (typeof uid == 'undefined' || req.user._id.toString() == uid)) next()
385
+ else if (req.user) res.unauthorized('You are not authorised to make this request.')
386
+ else res.unauthorized('Please sign in first.')
387
+ },
348
388
  }