Skip to content

Commit

Permalink
add permissions management (#827)
Browse files Browse the repository at this point in the history
* add permissions management

* hide required permission by default

* update permission description

* update strings

Co-authored-by: Brendan Early <[email protected]>
  • Loading branch information
Sneezry and mymindstorm authored Jan 16, 2022
1 parent 05dbda0 commit c3909f4
Show file tree
Hide file tree
Showing 12 changed files with 503 additions and 8 deletions.
54 changes: 54 additions & 0 deletions _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -445,5 +445,59 @@
},
"no_entires": {
"message": "No accounts to display. Add your first account now."

This comment was marked as off-topic.

Copy link
@gifblack

gifblack Jun 14, 2022

_locales/en/messages.json

},
"permissions": {
"message": "Permissions"
},
"permission_revoke": {
"message": "Revoke"
},
"permission_show_required_permissions": {
"message": "Show non-revocable permissions"
},
"permission_required": {
"message": "This is a required permission and cannot be revoked."
},
"permission_active_tab": {
"message": "Access to the current tab to scan QR codes."
},
"permission_storage": {
"message": "Access to browser storage to store account data."
},
"permission_identity": {
"message": "Allows sign in to 3rd party storage services."
},
"permission_clipboard_write": {
"message": "Grants write-only access to the clipboard to copy codes to clipboard when you click on the account."
},
"permission_context_menus": {
"message": "Adds Authenticator to context menu."
},
"permission_all_urls": {
"message": "Access to all websites to scan QR codes."
},
"permission_sync_clock": {
"message": "Allows clock sync with Google."
},
"permission_dropbox": {
"message": "Allows backup to Dropbox."
},
"permission_dropbox_cannot_revoke": {
"message": "You must disable Dropbox backup first."
},
"permission_drive": {
"message": "Allows backup to Google Drive."
},
"permission_drive_cannot_revoke": {
"message": "You must disable Google Drive backup first."
},
"permission_onedrive": {
"message": "Allows backup to OneDrive."
},
"permission_onedrive_cannot_revoke": {
"message": "You must disable OneDrive backup first."
},
"permission_unknown_permission": {
"message": "Unknown permission. If see this message, please send a bug report."
}
}
43 changes: 43 additions & 0 deletions sass/permissions.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
@import "ui";

[v-cloak] {
display: none;
}

* {
font-family: arial, "Microsoft YaHei";
}

p {
font-size: 16px;
}

#permissions {
width: 900px;
position: relative;
margin: 0 auto;
}

h2 {
margin-top: 3em;
}

button {
display: inline-grid;
padding: 10px 20px;
border: #ccc 1px solid;
background: white;
border-radius: 2px;
position: relative;
text-align: center;
align-items: center;
font-size: 16px;
color: gray;
cursor: pointer;
outline: none;
margin-left: 0px !important;

&:not(:disabled):hover {
color: black;
}
}
53 changes: 53 additions & 0 deletions src/components/Permissions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<template>
<div id="permissions" class="theme-normal">
<h1>Permissions</h1>
<div>
<input
type="checkbox"
id="showRequiredPermission"
v-model="showAllPermissions"
/>
<label for="showRequiredPermission">{{
i18n.permission_show_required_permissions
}}</label>
</div>
<div v-for="permission in permissions" :key="permission.id">
<h2>{{ permission.id }}</h2>
<p>{{ permission.description }}</p>
<p v-if="!permission.revocable">{{ i18n.permission_required }}</p>
<button
:disabled="!permission.revocable"
v-if="permission.revocable"
v-on:click="revoke(permission.id)"
>
{{ i18n.permission_revoke }}
</button>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import { Permission } from "../models/permission";
export default Vue.extend({
computed: {
permissions: function () {
return this.$store.state.permissions.permissions.filter(
(permission: Permission) => {
return this.showAllPermissions || permission.revocable;
}
);
},
},
data: function () {
return {
showAllPermissions: false,
};
},
methods: {
revoke(permissionId: string) {
this.$store.commit("permissions/revokePermission", permissionId);
},
},
});
</script>
25 changes: 17 additions & 8 deletions src/components/Popup/MenuPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@
</div>
<div id="menuBody">
<div class="menuList">
<a href="licenses.html" target="_blank" style="text-decoration: none">
<p v-bind:title="i18n.about">
<span><IconInfo /></span>{{ i18n.about }}
<p v-bind:title="i18n.advisor" v-on:click="showInfo('AdvisorPage')">
<span><IconAdvisor /></span>{{ i18n.advisor }}
</p>
<a
href="permissions.html"
target="_blank"
style="text-decoration: none"
>
<p v-bind:title="i18n.permissions">
<span><IconClipboardCheck /></span>{{ i18n.permissions }}
</p>
</a>
</div>
Expand All @@ -34,11 +41,6 @@
<span><IconWrench /></span>{{ i18n.resize_popup_page }}
</p>
</div>
<div class="menuList">
<p v-bind:title="i18n.advisor" v-on:click="showInfo('AdvisorPage')">
<span><IconAdvisor /></span>{{ i18n.advisor }}
</p>
</div>
<div class="menuList">
<p v-bind:title="i18n.feedback" v-on:click="openHelp()">
<span><IconComments /></span>{{ i18n.feedback }}
Expand All @@ -55,6 +57,11 @@
>
<span><IconCode /></span>{{ i18n.source }}
</p>
<a href="licenses.html" target="_blank" style="text-decoration: none">
<p v-bind:title="i18n.about">
<span><IconInfo /></span>{{ i18n.about }}
</p>
</a>
</div>
<div id="version">Version {{ version }}</div>
</div>
Expand All @@ -75,6 +82,7 @@ import IconAdvisor from "../../../svg/lightbulb.svg";
import IconComments from "../../../svg/comments.svg";
import IconGlobe from "../../../svg/globe.svg";
import IconCode from "../../../svg/code.svg";
import IconClipboardCheck from "../../../svg/clipboard-check.svg";
export default Vue.extend({
components: {
Expand All @@ -89,6 +97,7 @@ export default Vue.extend({
IconComments,
IconGlobe,
IconCode,
IconClipboardCheck,
},
computed: {
version: function () {
Expand Down
4 changes: 4 additions & 0 deletions src/definitions/module-interface.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,7 @@ interface AdvisorState {
insights: AdvisorInsightInterface[];
ignoreList: string[];
}

interface PermissionsState {
permissions: PermissionInterface[];
}
11 changes: 11 additions & 0 deletions src/definitions/permission.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
interface ValidationResult {
valid: boolean;
message?: string;
}

interface PermissionInterface {
id: string;
description: string;
revocable: boolean;
validation?: Array<() => ValidationResult>;
}
13 changes: 13 additions & 0 deletions src/models/permission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export class Permission implements PermissionInterface {
id: string;
description: string;
revocable: boolean;
validation?: Array<() => ValidationResult>;

constructor(permission: PermissionInterface) {
this.id = permission.id;
this.description = permission.description;
this.revocable = permission.revocable;
this.validation = permission.validation;
}
}
45 changes: 45 additions & 0 deletions src/permissions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Vue
import Vue from "vue";
import Vuex from "vuex";

// Components
import PermissionsView from "./components/Permissions.vue";
import CommonComponents from "./components/common/index";

// Other
import { loadI18nMessages } from "./store/i18n";
import { Permissions } from "./store/Permissions";

async function init() {
// i18n
Vue.prototype.i18n = await loadI18nMessages();

// Load modules
Vue.use(Vuex);

// Load common components globally
for (const component of CommonComponents) {
Vue.component(component.name, component.component);
}

// State
const store = new Vuex.Store({
modules: {
permissions: await new Permissions().getModule(),
},
});

const instance = new Vue({
render: (h) => h(PermissionsView),
store,
}).$mount("#permissions");

// Set title
try {
document.title = instance.i18n.extName;
} catch (e) {
console.error(e);
}
}

init();
Loading

0 comments on commit c3909f4

Please sign in to comment.