Access Control
For frontend applications, "access control" refers to whether pages are accessible and whether page elements are visible.
Setup
- Install the plugin
$ npm add @winner-fed/plugin-access -D$ yarn add @winner-fed/plugin-access -D$ pnpm add @winner-fed/plugin-access -D$ bun add @winner-fed/plugin-access -D- Enable the plugin in the
.winrcconfiguration file
import { defineConfig } from 'win';
export default defineConfig({
plugins: ['@winner-fed/plugin-access'],
routes: [{
path: '/',
name: 'Home',
component: 'index',
routes: [
{
path: 'admin',
name: 'Admin',
component: '@/components/admin'
},
{
path: 'normal',
name: 'Normal',
component: '@/components/normal'
}
]
}],
/**
* @name Access Control Plugin
* @doc https://winjs-dev.github.io/winjs-docs/plugins/access.html
*/
access: {
roles: {
admin: ['/admin'],
normal: ['/normal']
}
}
});Introduction
In this plugin design, one page permission corresponds to one route. For example, when accessing the '/admin' route, if the current role doesn't have permission for this route, the component will not be rendered.
export default {
access: {
roles: {
admin: ['/admin'],
normal: ['/normal']
}
}
};Usage example:
<template>
<Access :id="accessId">Only visible to Admin</Access>
<div v-access="accessId">Only visible to Admin</div>
</template>
<script setup lang="ts">
const accessId = '/admin';
</script>Note
We uniformly refer to pages and page elements as resources, and use resource IDs to identify and distinguish them:
- The resource ID of a page defaults to the page's route
path. For example, the routepathof pagepages/a.vueis/a. When the page accesses/a, the current page will be rendered, and/ais the page'saccessId. - Page elements' resource IDs have no default value and need to be customized.
Matching Rules
Exact Matching
The default matching rule for resources is exact matching. For example, if page pages/a.vue corresponds to route path /a, then /a is the page's resource ID. If we set:
access.setAccess(['/a']);Since the permission list contains /a, it indicates having permission for this page.
Fuzzy Matching
Page @id.vue will be mapped to dynamic route /:id. There are two ways to match this page:
- access.setAccess(['/:id'])
- access.setAccess(['/*'])
The second is fuzzy matching, where * represents any path. For example, if role admin needs full permissions:
export default {
access: {
roles: {
admin: ['*']
}
}
};Compile-time Configuration
When executing win dev or win build, runtime code is generated through this configuration. Configure in the .winrc.js configuration file:
export default {
access: {
roles: {
admin: ['/', '/admin', '/normal'],
},
},
};roles
Type:
Record<string, []>;Default:
{}Details:
Predefined role list.
keyis the role ID, andvalueis the resource list corresponding to the role ID.
Runtime Configuration
Configure in app.js
unAccessHandler
Type:
FunctionDefault:
nullDetails: When entering a route, if the page corresponding to the route doesn't belong to the visible resource list, entry will be paused and the
unAccessHandlerfunction will be called.Parameters
- router: Router instance created by createRouter
- to: Route being navigated to
- from: Route being navigated away from
- next: next function
Example:
import { access as accessApi } from 'winjs';
export const access = {
unAccessHandler ({ to, next }) {
const accesssIds = accessApi.getAccess();
if (to.path === '/404') {
accessApi.setAccess(accesssIds.concat(['/404']));
return next('/404');
}
if (!accesssIds.includes('/403')) {
accessApi.setAccess(accesssIds.concat(['/403']));
}
next('/403');
},
};noFoundHandler
- Type:
Function - Default:
null - Details: When entering a route, if the page corresponding to the route doesn't exist, the
noFoundHandlerfunction will be called. - Parameters
- router: Router instance created by createRouter
- to: Route being navigated to
- from: Route being navigated away from
- next: next function
Example:
import { access as accessApi } from 'winjs';
export const access = {
noFoundHandler ({ next }) {
const accesssIds = accessApi.getAccess();
if (!accesssIds.includes('/404')) {
accessApi.setAccess(accesssIds.concat(['/404']));
}
next('/404');
},
};ignoreAccess
- Type:
Array<string> - Default:
null - Details: Configure pages that should ignore access control validation.
Example:
export const access = {
ignoreAccess: ['/login'],
};API
WinJS uses custom directives, specifically the v-access directive, passing in the object returned by useAccess to control component rendering.
Plugin APIs are exported through winjs:
import { access } from 'winjs';access.hasAccess
- Type:
( accessId: string | number ) => Promise\<boolean\> - Details: Determine whether a resource is visible.
- Parameters:
- accessId: Resource ID
- Returns: Whether access is granted
access.isDataReady
- Type:
() => boolean - Details: Permissions can be set using asynchronous data.
isDataReadyis used to determine whether asynchronous data has finished loading. - Parameters: null
- Returns: Boolean
import { access } from 'winjs';
console.log(access.isDataReady());access.setRole
- Type:
Function - Details: Set the current role.
- Parameters:
- roleId: Role ID, has two types:
- String: Corresponds to the
keyin therolesconfiguration object. - Promise: The result of Promise resolve should correspond to the
keyin therolesconfiguration object.
- String: Corresponds to the
import { access } from 'winjs';
access.setRole('admin');access.getRole
- Type:
Function - Details: Get the current role.
import { access } from 'winjs';
access.getRole();access.setAccess
- Type:
Function - Details: Set the current access permissions.
- Parameters:
- accessIds: Array of resource IDs, has two types:
- Array: Array items correspond to the
keyin therolesconfiguration object. - Promise: The result of Promise resolve should be
Array<accessId>.
- Array: Array items correspond to the
import { access } from 'winjs';
access.setAccess(['/a', '/b', '/c']);access.getAccess
- Type:
Function - Details: Return the current list of visible resources.
- Parameters: null
import { access } from 'winjs';
access.getAccess();useAccess
- Type: Composition function
- Details: Determine whether a resource is visible.
- Parameters:
- accessId: Resource ID
- Returns:
ref
<template>
<div v-if="accessOnepicess">accessOnepicess</div>
</template>
<script>
import { useAccess } from 'winjs';
export default {
setup () {
const accessOnepicess = useAccess('/onepiece1');
return {
accessOnepicess,
};
},
};
</script>v-access
Pass accessId into the v-access directive. When accessId has permission, the DOM will be displayed; when there's no permission, the DOM will be hidden.
<template>
<div v-access="accessId">accessOnepicess</div>
</template>
<script>
export default {
setup () {
return {
accessId: 'accessOnepicess',
};
},
};
</script>Access Component
Pass accessId into the Access component. When accessId has permission, this component will be rendered; when there's no permission, this component will be hidden.
<template>
<access :id="accessId"> accessOnepicess</access>
</template>
<script>
export default {
setup () {
return {
accessId: 'accessOnepicess',
};
},
};
</script>