@live-change/access-control-frontend 0.0.3

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.
@@ -0,0 +1,71 @@
1
+ <template>
2
+ <SimpleNotification :notification="notification">
3
+ <div>
4
+ <UserIdentification :ownerType="notification.fromType" :owner="notification.from"
5
+ :data="notification.fromIdentification" inline />
6
+ Invited you to
7
+ <ObjectIdentification :objectType="notification.objectType" :object="notification.object" />
8
+ </div>
9
+ <div class="mt-2 ml-4" v-if="!notification.state">
10
+ <Button label="Accept" icon="pi pi-check" class="p-button-sm mr-2" @click="acceptInvitation" />
11
+ <Button label="Ignore" icon="pi pi-times" class="p-button-sm" @click="deleteNotification" />
12
+ </div>
13
+ <!-- <pre class="w-full overflow-hidden">{{ notification }}</pre>-->
14
+ </SimpleNotification>
15
+ </template>
16
+
17
+ <script setup>
18
+
19
+ import { SimpleNotification, UserIdentification, ObjectIdentification } from "@live-change/user-frontend"
20
+ import Button from "primevue/button"
21
+
22
+ import { useToast } from 'primevue/usetoast'
23
+ import { useConfirm } from 'primevue/useconfirm'
24
+ const confirm = useConfirm()
25
+ const toast = useToast()
26
+
27
+ const { notification } = defineProps({
28
+ notification: {
29
+ type: Object,
30
+ required: true
31
+ }
32
+ })
33
+
34
+ import { inject } from "vue"
35
+ const workingZone = inject('workingZone')
36
+
37
+ import { actions } from "@live-change/vue3-ssr"
38
+
39
+ const notificationApi = actions().notification
40
+ const accessControlApi = actions().accessControl
41
+
42
+ function deleteNotification() {
43
+ workingZone.addPromise('deleteNotification', (async () => {
44
+ await notificationApi.delete({ notification: notification.to || notification.id })
45
+ toast.add({
46
+ severity: 'warn', summary: 'Notification deleted',
47
+ detail: 'Notification has been deleted', life: 3000
48
+ })
49
+ })())
50
+ }
51
+
52
+ function acceptInvitation() {
53
+ workingZone.addPromise('acceptInvitation', (async () => {
54
+ const { objectType, object } = notification
55
+ await Promise.all([
56
+ accessControlApi.acceptInvitation({ objectType, object }),
57
+ notificationApi.markRead({ notification: notification.to || notification.id }),
58
+ notificationApi.mark({ notification: notification.to || notification.id, state: 'accepted' })
59
+ ])
60
+ toast.add({
61
+ severity: 'success', summary: 'Invitation Accepted',
62
+ detail: 'Invitation has been accepted', life: 3000
63
+ })
64
+ })())
65
+ }
66
+
67
+ </script>
68
+
69
+ <style scoped>
70
+
71
+ </style>
@@ -0,0 +1,6 @@
1
+ import { notificationTypes } from "@live-change/user-frontend"
2
+ import InviteNotification from "./InviteNotification.vue"
3
+
4
+ notificationTypes.accessControl_Invitation = {
5
+ component: InviteNotification
6
+ }
@@ -0,0 +1,55 @@
1
+ import {
2
+ createMemoryHistory,
3
+ createRouter as _createRouter,
4
+ createWebHistory
5
+ } from 'vue-router'
6
+
7
+ import configurationRoutes from "./configuration/routes.js"
8
+ import inviteRoutes from "./invite/routes.js"
9
+
10
+ import { userRoutes, installUserRedirects } from "@live-change/user-frontend"
11
+ import { dbAdminRoutes } from "@live-change/db-admin"
12
+
13
+ export function routes(config = {}) {
14
+ console.log("DB ROUTES", dbAdminRoutes({ prefix: '/_db' }))
15
+ const { prefix = '/', route = (r) => r } = config
16
+ return [
17
+ ...userRoutes({ ...config, prefix: prefix + 'user/' }),
18
+
19
+ ...configurationRoutes(config),
20
+ ...inviteRoutes(config),
21
+
22
+ route({
23
+ name: 'accessControl:testPage', path: prefix + '', meta: { },
24
+ component: () => import("./configuration/AccessControl.vue"),
25
+ props: {
26
+ objectType: 'example_Example',
27
+ object: 'one'
28
+ }
29
+ }),
30
+
31
+ ...dbAdminRoutes({ prefix: '/_db', route: r => ({ ...r, meta: { ...r.meta, raw: true }}) })
32
+ ]
33
+ }
34
+
35
+ export async function sitemap(route, api) {
36
+
37
+ }
38
+
39
+ import { client as useClient } from '@live-change/vue3-ssr'
40
+ import messageAuthRoutes from "../../../user-frontend/front/src/message-auth/routes";
41
+ import signRoutes from "../../../user-frontend/front/src/sign/routes";
42
+
43
+ export function createRouter(app, config) {
44
+ //console.log("APP CTX", app._context)
45
+ const client = useClient(app._context)
46
+ const router = _createRouter({
47
+ // use appropriate history implementation for server/client
48
+ // import.meta.env.SSR is injected by Vite.
49
+ history: import.meta.env.SSR ? createMemoryHistory() : createWebHistory(),
50
+ routes: routes(config)
51
+ })
52
+ installUserRedirects(router, app, config)
53
+ return router
54
+ }
55
+
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from 'vite'
2
+
3
+ import baseViteConfig from '@live-change/frontend-base/vite-config.js'
4
+
5
+ export default defineConfig(async ({ command, mode }) => {
6
+ return {
7
+ ...(await baseViteConfig({ command, mode })),
8
+
9
+
10
+ }
11
+ })
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@live-change/access-control-frontend",
3
+ "version": "0.0.3",
4
+ "scripts": {
5
+ "memDev": "lcli memDev --enableSessions --initScript ./init.js --dbAccess",
6
+ "localDevInit": "rm tmp.db; lcli localDev --enableSessions --initScript ./init.js",
7
+ "localDev": "lcli localDev --enableSessions",
8
+ "dev": "lcli dev --enableSessions",
9
+ "ssrDev": "lcli ssrDev --enableSessions",
10
+ "serveAllMem": "cross-env NODE_ENV=production lcli ssrServer --withApi --withServices --updateServices --enableSessions --withDb --dbBackend mem --createDb",
11
+ "serveAll": "cross-env NODE_ENV=production lcli ssrServer --withApi --withServices --updateServices --enableSessions",
12
+ "serve": "cross-env NODE_ENV=production lcli ssrServer --enableSessions",
13
+ "apiServer": "lcli apiServer --enableSessions",
14
+ "devApiServer": "lcli devApiServer --enableSessions",
15
+ "memApiServer": "lcli memApiServer --enableSessions",
16
+ "build": "cd front; yarn build:client && yarn build:server",
17
+ "build:client": "cd front; vite build --ssrManifest --outDir dist/client",
18
+ "build:server": "cd front; vite build --ssr src/entry-server.js --outDir dist/server",
19
+ "generate": "vite build --ssrManifest --outDir dist/static && yarn build:server && node prerender",
20
+ "debug": "node --inspect-brk server"
21
+ },
22
+ "dependencies": {
23
+ "@live-change/framework": "0.6.5",
24
+ "@live-change/cli": "0.6.5",
25
+ "@live-change/dao": "0.4.13",
26
+ "@live-change/dao-vue3": "0.4.13",
27
+ "@live-change/dao-websocket": "0.4.13",
28
+ "@live-change/vue3-ssr": "0.2.14",
29
+ "@live-change/vue3-components": "0.2.12",
30
+ "@live-change/session-service": "0.2.39",
31
+ "@live-change/user-service": "0.2.37",
32
+ "@live-change/password-authentication-service": "0.2.39",
33
+ "@live-change/secret-link-service": "0.2.39",
34
+ "@live-change/secret-code-service": "0.2.39",
35
+ "@live-change/access-control-service": "0.2.37",
36
+ "@live-change/user-frontend": "0.0.3",
37
+ "@live-change/db-admin": "0.5.12",
38
+ "@vitejs/plugin-vue": "^2.3.1",
39
+ "@vitejs/plugin-vue-jsx": "^1.3.10",
40
+ "@vue/compiler-sfc": "^3.2.33",
41
+ "@vueuse/core": "^8.3.1",
42
+ "v-shared-element": "3.1.0",
43
+ "vue3-scroll-border": "0.1.2",
44
+ "codeceptjs-assert": "^0.0.5",
45
+ "compression": "^1.7.4",
46
+ "cross-env": "^7.0.3",
47
+ "get-port-sync": "1.0.1",
48
+ "primeicons": "^5.0.0",
49
+ "primevue": "^3.15.0",
50
+ "primeflex": "^3.2.1",
51
+ "rollup-plugin-node-builtins": "^2.1.2",
52
+ "serialize-javascript": "^6.0.0",
53
+ "serve-static": "^1.15.0",
54
+ "vite": "^2.9.6",
55
+ "vue": "^3.2.33",
56
+ "vue-meta": "^3.0.0-alpha.9",
57
+ "vue-router": "^4.0.14",
58
+ "vite-plugin-compression": "0.5.1",
59
+ "vite-plugin-vue-images": "^0.6.1",
60
+ "rollup-plugin-visualizer": "5.6.0"
61
+ },
62
+ "devDependencies": {
63
+ "@live-change/codeceptjs-helper": "0.6.5",
64
+ "@wdio/selenium-standalone-service": "^7.19.5",
65
+ "codeceptjs": "^3.3.1",
66
+ "playwright": "^1.21.1",
67
+ "random-profile-generator": "^2.3.0",
68
+ "txtgen": "^3.0.1",
69
+ "generate-password": "1.7.0",
70
+ "webdriverio": "^7.19.5"
71
+ },
72
+ "author": "",
73
+ "license": "ISC",
74
+ "description": ""
75
+ }
package/server/init.js ADDED
@@ -0,0 +1,84 @@
1
+ const App = require('@live-change/framework')
2
+ const app = App.app()
3
+
4
+ module.exports = async function(services) {
5
+
6
+ const { PasswordAuthentication } = services.passwordAuthentication.models
7
+ const { PublicAccess, Access, AccessRequest, AccessInvitation } = services.accessControl.models
8
+
9
+ async function createUser(name, email, password, user = app.generateUid()) {
10
+ const passwordHash = PasswordAuthentication.definition.properties.passwordHash.preFilter(password)
11
+ await services.user.models.User.create({ id: user, roles: [] })
12
+ await PasswordAuthentication.create({ id: user, user, passwordHash })
13
+ await services.email.models.Email.create({ id: email, email, user })
14
+ await services.userIdentification.models.Identification.create({
15
+ id: App.encodeIdentifier(['user_User', user]), sessionOrUserType: 'user_User', sessionOrUser: user,
16
+ name
17
+ })
18
+ return {
19
+ id: user,
20
+ name,
21
+ email,
22
+ password
23
+ }
24
+ }
25
+
26
+ const session = 'GOzz0WylRDklhLCSppS6bwRYUeIQJqzt'
27
+
28
+ //console.log("MDL", services.passwordAuthentication.models.PasswordAuthentication)
29
+
30
+ const user1 = await createUser('Test User 1', 'test1@test.com', 'Testy123', 'u1')
31
+ const user2 = await createUser('Test User 2 with very long name!', 'test2@test.com', 'Testy123')
32
+ const user3 = await createUser('Test User 3', 'test3@test.com', 'Testy123')
33
+
34
+ await services.user.models.AuthenticatedUser.create({ id: session, session, user: user2.id })
35
+
36
+ await services.notification.models.Notification.create({
37
+ "id": app.generateUid(),
38
+ "notificationType": "accessControl_Invitation",
39
+ "objectType": "example_Example",
40
+ "object": "two",
41
+ "fromType": "user_User",
42
+ "from": user1.id,
43
+ "sessionOrUserType": "user_User",
44
+ "sessionOrUser": user2.id,
45
+ "time": "2022-05-23T13:13:25.501Z",
46
+ "readState": "new"
47
+ })
48
+
49
+ /* await PublicAccess.create({
50
+ id: App.encodeIdentifier(['example_Example', 'one']),
51
+ objectType: 'example_Example', object: 'one',
52
+ userRoles: ['reader'],
53
+ sessionRoles: []
54
+ })*/
55
+
56
+ await Access.create({
57
+ id: App.encodeIdentifier(['user_User', user1.id, 'example_Example', 'one']),
58
+ sessionOrUserType: 'user_User', sessionOrUser: user1.id,
59
+ objectType: 'example_Example', object: 'one',
60
+ roles: ['administrator']
61
+ })
62
+
63
+ await AccessRequest.create({
64
+ id: App.encodeIdentifier(['user_User', user2.id, 'example_Example', 'one']),
65
+ sessionOrUserType: 'user_User', sessionOrUser: user2.id,
66
+ objectType: 'example_Example', object: 'one',
67
+ roles: ['writer']
68
+ })
69
+
70
+ await AccessInvitation.create({
71
+ id: App.encodeIdentifier(['user_User', user3.id, 'example_Example', 'one']),
72
+ contactOrUserType: 'user_User', contactOrUser: user3.id,
73
+ objectType: 'example_Example', object: 'one',
74
+ roles: ['moderator']
75
+ })
76
+
77
+ await AccessInvitation.create({
78
+ id: App.encodeIdentifier(['email_Email', 'tester@test.com', 'example_Example', 'one']),
79
+ contactOrUserType: 'email_Email', contactOrUser: 'tester@test.com',
80
+ objectType: 'example_Example', object: 'one',
81
+ roles: ['moderator']
82
+ })
83
+
84
+ }
@@ -0,0 +1,53 @@
1
+ const lcp = require("@live-change/pattern")
2
+
3
+ const clientKeys = (client) => [
4
+ { key: 'user', value: client.user },
5
+ { key: 'session', value: client.session },
6
+ { key: 'ip', value: client.ip }
7
+ ]
8
+
9
+ const failedAuthCodes = lcp.chain([
10
+ { type: "wrong-secret-code", id: "1st-failed-secret-code" },
11
+ { eq: "ip", expire: "10m" },
12
+ { type: "wrong-secret-code", id: "2nd-failed-secret-code" },
13
+ { eq: "ip", expire: "10m" },
14
+ { type: "wrong-secret-code", id: "3rd-failed-secret-code",
15
+ actions: [
16
+ { type: 'ban', keys: ['ip'], ban: { type: 'captcha', actions: ['checkSecretCode'], expire: "30m" } }
17
+ ]
18
+ }
19
+ ]).model
20
+
21
+ const patterns = lcp.mergeModels(
22
+ //failedAuthCodes
23
+ )
24
+
25
+ const counters = [
26
+ {
27
+ id: 'wrong-codes-captcha',
28
+ match: ['wrong-secret-code'],
29
+ keys: ['ip'],
30
+ max: 2,
31
+ duration: '1m',
32
+ actions: [
33
+ { type: 'ban', keys: ['ip'], ban: { type: 'captcha', actions: ['checkSecretCode'], expire: "30m" } }
34
+ ]
35
+ },
36
+ {
37
+ id: 'wrong-codes-ban',
38
+ visible: true,
39
+ match: ['wrong-secret-code'],
40
+ keys: ['ip'],
41
+ max: 5,
42
+ duration: '10m',
43
+ actions: [
44
+ { type: 'ban', keys: ['ip'], ban: { type: 'block', actions: ['checkSecretCode'], expire: "2m" } }
45
+ ]
46
+ }
47
+ ]
48
+
49
+ module.exports = {
50
+ clientKeys,
51
+ patterns,
52
+ counters
53
+ }
@@ -0,0 +1,84 @@
1
+ const contactTypes = ['email']
2
+
3
+ module.exports = {
4
+ services: [
5
+ {
6
+ name: 'timer',
7
+ path: '@live-change/timer-service'
8
+ },
9
+ {
10
+ name: 'session',
11
+ path: '@live-change/session-service',
12
+ createSessionOnUpdate: true
13
+ },
14
+ {
15
+ name: 'user',
16
+ path: '@live-change/user-service'
17
+ },
18
+ {
19
+ name: 'email',
20
+ path: '@live-change/email-service'
21
+ },
22
+ {
23
+ name: 'security',
24
+ path: '@live-change/security-service',
25
+ ...require('./security.config.js')
26
+ },
27
+ {
28
+ name: 'secretLink',
29
+ path: '@live-change/secret-link-service'
30
+ },
31
+ {
32
+ name: 'secretCode',
33
+ path: '@live-change/secret-code-service'
34
+ },
35
+ {
36
+ name: 'messageAuthentication',
37
+ path: '@live-change/message-authentication-service',
38
+ contactTypes,
39
+ signUp: true,
40
+ signIn: true,
41
+ connect: true
42
+ },
43
+ {
44
+ name: 'passwordAuthentication',
45
+ path: '@live-change/password-authentication-service',
46
+ contactTypes,
47
+ signInWithoutPassword: true
48
+ },
49
+ {
50
+ name: 'userIdentification',
51
+ path: '@live-change/user-identification-service'
52
+ },
53
+ {
54
+ name: 'identicon',
55
+ path: '@live-change/identicon-service'
56
+ },
57
+ {
58
+ name: 'accessControl',
59
+ path: '@live-change/access-control-service',
60
+ createSessionOnUpdate: true,
61
+ contactTypes,
62
+ },
63
+ {
64
+ name: 'notification',
65
+ path: '@live-change/notification-service',
66
+ contactTypes,
67
+ notificationTypes: ['accessControl_Invitation'],
68
+ fields: {
69
+ objectType: {
70
+ type: String
71
+ },
72
+ object: {
73
+ type: String
74
+ },
75
+ fromType: {
76
+ type: String
77
+ },
78
+ from: {
79
+ type: String
80
+ }
81
+ }
82
+ },
83
+ ]
84
+ }