diff --git a/server/db/migrations/3.0.0.js b/server/db/migrations/3.0.0.js index ae3f90a2..0ac87fc8 100644 --- a/server/db/migrations/3.0.0.js +++ b/server/db/migrations/3.0.0.js @@ -63,13 +63,11 @@ exports.up = async knex => { table.uuid('id').notNullable().primary().defaultTo(knex.raw('gen_random_uuid()')) table.string('module').notNullable() table.boolean('isEnabled').notNullable().defaultTo(false) - table.integer('order').unsigned().notNullable().defaultTo(0) table.string('displayName').notNullable().defaultTo('') table.jsonb('config').notNullable().defaultTo('{}') table.boolean('selfRegistration').notNullable().defaultTo(false) table.jsonb('domainWhitelist').notNullable().defaultTo('[]') table.jsonb('autoEnrollGroups').notNullable().defaultTo('[]') - table.jsonb('hideOnSites').notNullable().defaultTo('[]') }) .createTable('commentProviders', table => { table.uuid('id').notNullable().primary().defaultTo(knex.raw('gen_random_uuid()')) diff --git a/server/graph/resolvers/authentication.js b/server/graph/resolvers/authentication.js index 93752ffb..a3661a8a 100644 --- a/server/graph/resolvers/authentication.js +++ b/server/graph/resolvers/authentication.js @@ -31,18 +31,18 @@ module.exports = { async authStrategies () { return WIKI.data.authentication.map(stg => ({ ...stg, - isAvailable: stg.isAvailable === true, - props: _.sortBy(_.transform(stg.props, (res, value, key) => { - res.push({ - key, - value: JSON.stringify(value) - }) - }, []), 'key') + isAvailable: stg.isAvailable === true })) }, /** * Fetch active authentication strategies */ + async authActiveStrategies (obj, args, context) { + return WIKI.models.authentication.getStrategies() + }, + /** + * Fetch site authentication strategies + */ async authSiteStrategies (obj, args, context, info) { let strategies = await WIKI.models.authentication.getStrategies() strategies = strategies.map(stg => { @@ -268,14 +268,9 @@ module.exports = { } } }, - AuthenticationStrategy: { - icon (ap, args) { - return fs.readFile(path.join(WIKI.ROOTPATH, `assets/svg/auth-icon-${ap.key}.svg`), 'utf8').catch(err => { - if (err.code === 'ENOENT') { - return null - } - throw err - }) + AuthenticationActiveStrategy: { + strategy (obj, args, context) { + return _.find(WIKI.data.authentication, ['key', obj.module]) } } } diff --git a/server/graph/schemas/authentication.graphql b/server/graph/schemas/authentication.graphql index 22acf85f..9549a02d 100644 --- a/server/graph/schemas/authentication.graphql +++ b/server/graph/schemas/authentication.graphql @@ -9,9 +9,11 @@ extend type Query { authStrategies: [AuthenticationStrategy] + authActiveStrategies: [AuthenticationActiveStrategy] + authSiteStrategies( siteId: UUID! - enabledOnly: Boolean + visibleOnly: Boolean ): [AuthenticationSiteStrategy] } @@ -73,7 +75,7 @@ extend type Mutation { type AuthenticationStrategy { key: String - props: [KeyValuePair] + props: JSON title: String description: String isAvailable: Boolean @@ -81,22 +83,29 @@ type AuthenticationStrategy { usernameType: String logo: String color: String + vendor: String website: String icon: String } -type AuthenticationSiteStrategy { - key: String +type AuthenticationActiveStrategy { + id: UUID strategy: AuthenticationStrategy displayName: String - order: Int isEnabled: Boolean - config: [KeyValuePair] + config: JSON selfRegistration: Boolean domainWhitelist: [String] autoEnrollGroups: [Int] } +type AuthenticationSiteStrategy { + id: UUID + activeStrategy: AuthenticationActiveStrategy + order: Int + isVisible: Boolean +} + type AuthenticationLoginResponse { operation: Operation jwt: String diff --git a/server/helpers/common.js b/server/helpers/common.js index e2a38a35..44fd39f1 100644 --- a/server/helpers/common.js +++ b/server/helpers/common.js @@ -29,11 +29,12 @@ module.exports = { default: defaultValue, type: (value.type || value).toLowerCase(), title: value.title || _.startCase(key), - hint: value.hint || false, + hint: value.hint || '', enum: value.enum || false, + enumDisplay: value.enumDisplay || 'select', multiline: value.multiline || false, sensitive: value.sensitive || false, - maxWidth: value.maxWidth || 0, + icon: value.icon || 'rename', order: value.order || 100 }) return result diff --git a/server/models/authentication.js b/server/models/authentication.js index ba6b49d4..6f596ad0 100644 --- a/server/models/authentication.js +++ b/server/models/authentication.js @@ -51,13 +51,14 @@ module.exports = class Authentication extends Model { for (const dir of authenticationDirs) { const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/authentication', dir, 'definition.yml'), 'utf8') const defParsed = yaml.load(def) + if (!defParsed.isAvailable) { continue } defParsed.key = dir defParsed.props = commonHelper.parseModuleProps(defParsed.props) - WIKI.data.analytics.push(defParsed) + WIKI.data.authentication.push(defParsed) WIKI.logger.debug(`Loaded authentication module definition ${dir}: [ OK ]`) } - WIKI.logger.info(`Loaded ${WIKI.data.analytics.length} authentication module definitions: [ OK ]`) + WIKI.logger.info(`Loaded ${WIKI.data.authentication.length} authentication module definitions: [ OK ]`) } catch (err) { WIKI.logger.error(`Failed to scan or load authentication providers: [ FAILED ]`) WIKI.logger.error(err) diff --git a/server/modules/authentication/auth0/definition.yml b/server/modules/authentication/auth0/definition.yml index 9f475181..54a701cb 100644 --- a/server/modules/authentication/auth0/definition.yml +++ b/server/modules/authentication/auth0/definition.yml @@ -3,6 +3,7 @@ title: Auth0 description: Auth0 provides universal identity platform for web, mobile, IoT, and internal applications. author: requarks.io logo: https://static.requarks.io/logo/auth0.svg +icon: /_assets/icons/ultraviolet-auth0.svg color: deep-orange website: https://auth0.com/ isAvailable: true diff --git a/server/modules/authentication/azure/definition.yml b/server/modules/authentication/azure/definition.yml index ad7d41eb..f213b3c7 100644 --- a/server/modules/authentication/azure/definition.yml +++ b/server/modules/authentication/azure/definition.yml @@ -1,8 +1,9 @@ key: azure title: Azure Active Directory -description: Azure Active Directory (Azure AD) is Microsoft’s multi-tenant, cloud-based directory, and identity management service that combines core directory services, application access management, and identity protection into a single solution. +description: Azure Active Directory (Azure AD) is Microsoft's multi-tenant, cloud-based directory, and identity management service that combines core directory services, application access management, and identity protection into a single solution. author: requarks.io logo: https://static.requarks.io/logo/azure.svg +icon: /_assets/icons/ultraviolet-azure.svg color: blue darken-3 website: https://azure.microsoft.com/services/active-directory/ isAvailable: true diff --git a/server/modules/authentication/cas/definition.yml b/server/modules/authentication/cas/definition.yml index 912840eb..35b423d7 100644 --- a/server/modules/authentication/cas/definition.yml +++ b/server/modules/authentication/cas/definition.yml @@ -3,6 +3,7 @@ title: CAS description: The Central Authentication Service (CAS) is a single sign-on protocol for the web. author: requarks.io logo: https://static.requarks.io/logo/cas.svg +icon: /_assets/icons/ultraviolet-cas.svg color: green darken-2 website: https://apereo.github.io/cas/ useForm: false diff --git a/server/modules/authentication/discord/definition.yml b/server/modules/authentication/discord/definition.yml index e30becba..1d0e517d 100644 --- a/server/modules/authentication/discord/definition.yml +++ b/server/modules/authentication/discord/definition.yml @@ -3,6 +3,7 @@ title: Discord description: Discord is a proprietary freeware VoIP application designed for gaming communities, that specializes in text, video and audio communication between users in a chat channel. author: requarks.io logo: https://static.requarks.io/logo/discord.svg +icon: /_assets/icons/ultraviolet-discord.svg color: indigo lighten-2 website: https://discord.com/ isAvailable: true diff --git a/server/modules/authentication/dropbox/definition.yml b/server/modules/authentication/dropbox/definition.yml index 9fc8ce05..11ea43ce 100644 --- a/server/modules/authentication/dropbox/definition.yml +++ b/server/modules/authentication/dropbox/definition.yml @@ -3,6 +3,7 @@ title: Dropbox description: Dropbox is a file hosting service that offers cloud storage, file synchronization, personal cloud, and client software. author: requarks.io logo: https://static.requarks.io/logo/dropbox.svg +icon: /_assets/icons/ultraviolet-dropbox.svg color: blue darken-2 website: https://dropbox.com isAvailable: true diff --git a/server/modules/authentication/facebook/definition.yml b/server/modules/authentication/facebook/definition.yml index 90bd7e20..fc0e668c 100644 --- a/server/modules/authentication/facebook/definition.yml +++ b/server/modules/authentication/facebook/definition.yml @@ -3,6 +3,7 @@ title: Facebook description: Facebook is an online social media and social networking service company. author: requarks.io logo: https://static.requarks.io/logo/facebook.svg +icon: /_assets/icons/ultraviolet-facebook.svg color: indigo website: https://facebook.com/ isAvailable: true diff --git a/server/modules/authentication/firebase/authentication.js b/server/modules/authentication/firebase/authentication.js deleted file mode 100644 index 344cd8e3..00000000 --- a/server/modules/authentication/firebase/authentication.js +++ /dev/null @@ -1,36 +0,0 @@ -/* global WIKI */ - -// ------------------------------------ -// Firebase Account -// ------------------------------------ - -// INCOMPLETE / TODO - -const FirebaseStrategy = require('passport-github2').Strategy -const _ = require('lodash') - -module.exports = { - init (passport, conf) { - passport.use(conf.key, - new FirebaseStrategy({ - clientID: conf.clientId, - clientSecret: conf.clientSecret, - callbackURL: conf.callbackURL, - scope: ['user:email'] - }, async (req, accessToken, refreshToken, profile, cb) => { - try { - const user = await WIKI.models.users.processProfile({ - providerKey: req.params.strategy, - profile: { - ...profile, - picture: _.get(profile, 'photos[0].value', '') - } - }) - cb(null, user) - } catch (err) { - cb(err, null) - } - } - )) - } -} diff --git a/server/modules/authentication/firebase/definition.yml b/server/modules/authentication/firebase/definition.yml deleted file mode 100644 index b8efe789..00000000 --- a/server/modules/authentication/firebase/definition.yml +++ /dev/null @@ -1,11 +0,0 @@ -key: firebase -title: Firebase -description: Firebase is Google's mobile platform that helps you quickly develop high-quality apps and grow your business. -author: requarks.io -logo: https://static.requarks.io/logo/firebase.svg -color: yellow darken-3 -website: https://firebase.google.com/ -isAvailable: false -useForm: false -props: {} - diff --git a/server/modules/authentication/github/definition.yml b/server/modules/authentication/github/definition.yml index 691e24e9..93022b5d 100644 --- a/server/modules/authentication/github/definition.yml +++ b/server/modules/authentication/github/definition.yml @@ -3,6 +3,7 @@ title: GitHub description: GitHub Inc. is a web-based hosting service for version control using Git. author: requarks.io logo: https://static.requarks.io/logo/github.svg +icon: /_assets/icons/ultraviolet-github.svg color: grey darken-3 website: https://github.com isAvailable: true diff --git a/server/modules/authentication/gitlab/definition.yml b/server/modules/authentication/gitlab/definition.yml index e18dccb8..ce3407c2 100644 --- a/server/modules/authentication/gitlab/definition.yml +++ b/server/modules/authentication/gitlab/definition.yml @@ -3,6 +3,7 @@ title: GitLab description: GitLab is a web-based DevOps lifecycle tool that provides a Git-repository manager providing wiki, issue-tracking and CI/CD pipeline features. author: requarks.io logo: https://static.requarks.io/logo/gitlab.svg +icon: /_assets/icons/ultraviolet-gitlab.svg color: deep-orange website: https://gitlab.com isAvailable: true diff --git a/server/modules/authentication/google/definition.yml b/server/modules/authentication/google/definition.yml index 51747c37..435c6828 100644 --- a/server/modules/authentication/google/definition.yml +++ b/server/modules/authentication/google/definition.yml @@ -3,6 +3,7 @@ title: Google description: Google specializes in Internet-related services and products, which include online advertising technologies, search engine, cloud computing, software, and hardware. author: requarks.io logo: https://static.requarks.io/logo/google.svg +icon: /_assets/icons/ultraviolet-google.svg color: red darken-1 website: https://console.developers.google.com/ isAvailable: true diff --git a/server/modules/authentication/keycloak/definition.yml b/server/modules/authentication/keycloak/definition.yml index df8ca666..59aaf38b 100644 --- a/server/modules/authentication/keycloak/definition.yml +++ b/server/modules/authentication/keycloak/definition.yml @@ -3,6 +3,7 @@ title: Keycloak description: Keycloak is an open source software product to allow single sign-on with Identity Management and Access Management aimed at modern applications and services. author: D4uS1 logo: https://static.requarks.io/logo/keycloak.svg +icon: /_assets/icons/ultraviolet-keycloak.svg color: blue-grey darken-2 website: https://www.keycloak.org/ useForm: false diff --git a/server/modules/authentication/ldap/definition.yml b/server/modules/authentication/ldap/definition.yml index 8b0b1b2d..af982089 100644 --- a/server/modules/authentication/ldap/definition.yml +++ b/server/modules/authentication/ldap/definition.yml @@ -3,7 +3,9 @@ title: LDAP / Active Directory description: Active Directory is a directory service that Microsoft developed for the Windows domain networks. author: requarks.io logo: https://static.requarks.io/logo/active-directory.svg +icon: /_assets/icons/ultraviolet-windows8.svg color: blue darken-3 +vendor: Microsoft Corporation website: https://www.microsoft.com/windowsserver isAvailable: true useForm: true diff --git a/server/modules/authentication/local/definition.yml b/server/modules/authentication/local/definition.yml index e4157ed6..7efaffd3 100644 --- a/server/modules/authentication/local/definition.yml +++ b/server/modules/authentication/local/definition.yml @@ -3,8 +3,10 @@ title: Local Database description: Built-in authentication for Wiki.js author: requarks.io logo: https://static.requarks.io/logo/wikijs.svg +icon: /_assets/icons/ultraviolet-data-protection.svg color: primary -website: https://wiki.js.org +vendor: 'Wiki.js' +website: 'https://js.wiki' isAvailable: true useForm: true usernameType: email diff --git a/server/modules/authentication/microsoft/definition.yml b/server/modules/authentication/microsoft/definition.yml index 62cd3255..bf6f6b06 100644 --- a/server/modules/authentication/microsoft/definition.yml +++ b/server/modules/authentication/microsoft/definition.yml @@ -3,6 +3,7 @@ title: Microsoft description: Microsoft is a software company, best known for it's Windows, Office, Azure, Xbox and Surface products. author: requarks.io logo: https://static.requarks.io/logo/microsoft.svg +icon: /_assets/icons/ultraviolet-microsoft.svg color: blue website: https://apps.dev.microsoft.com/ isAvailable: false diff --git a/server/modules/authentication/oauth2/definition.yml b/server/modules/authentication/oauth2/definition.yml index 0621aa39..203b1a7c 100644 --- a/server/modules/authentication/oauth2/definition.yml +++ b/server/modules/authentication/oauth2/definition.yml @@ -3,6 +3,7 @@ title: Generic OAuth2 description: OAuth 2.0 is the industry-standard protocol for authorization. author: requarks.io logo: https://static.requarks.io/logo/oauth2.svg +icon: /_assets/icons/ultraviolet-oauth2.svg color: blue-grey darken-2 website: https://oauth.net/2/ isAvailable: true diff --git a/server/modules/authentication/oidc/definition.yml b/server/modules/authentication/oidc/definition.yml index 02812c4f..68a6ffc1 100644 --- a/server/modules/authentication/oidc/definition.yml +++ b/server/modules/authentication/oidc/definition.yml @@ -3,6 +3,7 @@ title: Generic OpenID Connect / OAuth2 description: OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. author: requarks.io logo: https://static.requarks.io/logo/oidc.svg +icon: /_assets/icons/ultraviolet-openid.svg color: blue-grey darken-2 website: http://openid.net/connect/ isAvailable: true diff --git a/server/modules/authentication/okta/definition.yml b/server/modules/authentication/okta/definition.yml index 734b5c92..74a16823 100644 --- a/server/modules/authentication/okta/definition.yml +++ b/server/modules/authentication/okta/definition.yml @@ -3,6 +3,7 @@ title: Okta description: Okta provide secure identity management and single sign-on to any application. author: requarks.io logo: https://static.requarks.io/logo/okta.svg +icon: /_assets/icons/ultraviolet-okta.svg color: blue darken-1 website: https://www.okta.com/ isAvailable: true diff --git a/server/modules/authentication/rocketchat/definition.yml b/server/modules/authentication/rocketchat/definition.yml index a47af49c..e04a1724 100644 --- a/server/modules/authentication/rocketchat/definition.yml +++ b/server/modules/authentication/rocketchat/definition.yml @@ -3,6 +3,7 @@ title: Rocket.chat description: Communicate and collaborate with your team, share files, chat in real-time, or switch to video/audio conferencing. author: requarks.io logo: https://static.requarks.io/logo/rocketchat.svg +icon: /_assets/icons/ultraviolet-rocketchat.svg color: red accent-3 website: https://rocket.chat/ isAvailable: true diff --git a/server/modules/authentication/saml/definition.yml b/server/modules/authentication/saml/definition.yml index bfb24d15..c3d0e7ff 100644 --- a/server/modules/authentication/saml/definition.yml +++ b/server/modules/authentication/saml/definition.yml @@ -3,6 +3,7 @@ title: SAML 2.0 description: Security Assertion Markup Language 2.0 (SAML 2.0) is a version of the SAML standard for exchanging authentication and authorization data between security domains. author: requarks.io logo: https://static.requarks.io/logo/saml.svg +icon: /_assets/icons/ultraviolet-saml.svg color: red darken-3 website: https://wiki.oasis-open.org/security/FrontPage isAvailable: true diff --git a/server/modules/authentication/slack/definition.yml b/server/modules/authentication/slack/definition.yml index f5900b0f..6c57d951 100644 --- a/server/modules/authentication/slack/definition.yml +++ b/server/modules/authentication/slack/definition.yml @@ -3,6 +3,7 @@ title: Slack description: Slack is a cloud-based set of proprietary team collaboration tools and services. author: requarks.io logo: https://static.requarks.io/logo/slack.svg +icon: /_assets/icons/ultraviolet-slack.svg color: green website: https://api.slack.com/docs/oauth isAvailable: true diff --git a/server/modules/authentication/twitch/definition.yml b/server/modules/authentication/twitch/definition.yml index aedda607..84f7587a 100644 --- a/server/modules/authentication/twitch/definition.yml +++ b/server/modules/authentication/twitch/definition.yml @@ -3,6 +3,7 @@ title: Twitch description: Twitch is a live streaming video platform. author: requarks.io logo: https://static.requarks.io/logo/twitch.svg +icon: /_assets/icons/ultraviolet-twitch.svg color: indigo darken-2 website: https://dev.twitch.tv/docs/authentication/ isAvailable: true diff --git a/ux/public/_assets/icons/ultraviolet-auth0.svg b/ux/public/_assets/icons/ultraviolet-auth0.svg new file mode 100644 index 00000000..801cbd26 --- /dev/null +++ b/ux/public/_assets/icons/ultraviolet-auth0.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/ux/public/_assets/icons/ultraviolet-gitlab.svg b/ux/public/_assets/icons/ultraviolet-gitlab.svg new file mode 100644 index 00000000..c0fdee5c --- /dev/null +++ b/ux/public/_assets/icons/ultraviolet-gitlab.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/ux/public/_assets/icons/ultraviolet-keycloak.svg b/ux/public/_assets/icons/ultraviolet-keycloak.svg new file mode 100644 index 00000000..eaa496c8 --- /dev/null +++ b/ux/public/_assets/icons/ultraviolet-keycloak.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/ux/public/_assets/icons/ultraviolet-oauth2.svg b/ux/public/_assets/icons/ultraviolet-oauth2.svg new file mode 100644 index 00000000..a85fa2f3 --- /dev/null +++ b/ux/public/_assets/icons/ultraviolet-oauth2.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/ux/public/_assets/icons/ultraviolet-okta.svg b/ux/public/_assets/icons/ultraviolet-okta.svg new file mode 100644 index 00000000..868851d7 --- /dev/null +++ b/ux/public/_assets/icons/ultraviolet-okta.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/ux/public/_assets/icons/ultraviolet-openid.svg b/ux/public/_assets/icons/ultraviolet-openid.svg new file mode 100644 index 00000000..82bf0459 --- /dev/null +++ b/ux/public/_assets/icons/ultraviolet-openid.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/ux/public/_assets/icons/ultraviolet-rename.svg b/ux/public/_assets/icons/ultraviolet-rename.svg new file mode 100644 index 00000000..d9e4bcb7 --- /dev/null +++ b/ux/public/_assets/icons/ultraviolet-rename.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ux/public/_assets/icons/ultraviolet-rocketchat.svg b/ux/public/_assets/icons/ultraviolet-rocketchat.svg new file mode 100644 index 00000000..2381cf64 --- /dev/null +++ b/ux/public/_assets/icons/ultraviolet-rocketchat.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/ux/public/_assets/icons/ultraviolet-saml.svg b/ux/public/_assets/icons/ultraviolet-saml.svg new file mode 100644 index 00000000..69c8c806 --- /dev/null +++ b/ux/public/_assets/icons/ultraviolet-saml.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/ux/public/_assets/icons/ultraviolet-twitch.svg b/ux/public/_assets/icons/ultraviolet-twitch.svg index 263ee07b..689aa92a 100644 --- a/ux/public/_assets/icons/ultraviolet-twitch.svg +++ b/ux/public/_assets/icons/ultraviolet-twitch.svg @@ -1 +1,9 @@ - \ No newline at end of file + + + + + + + + + diff --git a/ux/src/i18n/locales/en.json b/ux/src/i18n/locales/en.json index 9689bf8a..652dd886 100644 --- a/ux/src/i18n/locales/en.json +++ b/ux/src/i18n/locales/en.json @@ -1443,5 +1443,11 @@ "admin.utilities.exportHint": "Export content to tarball for backup / migration.", "admin.utilities.importHint": "Import content from a tarball backup or a 2.X backup.", "admin.utilities.flushCache": "Flush Cache", - "admin.utilities.flushCacheHint": "Pages and Assets are cached to disk for better performance. You can flush the cache to force all content to be fetched from the DB again." + "admin.utilities.flushCacheHint": "Pages and Assets are cached to disk for better performance. You can flush the cache to force all content to be fetched from the DB again.", + "admin.auth.enabledForced": "This strategy cannot be disabled.", + "admin.auth.enabled": "Enabled", + "admin.auth.enabledHint": "Should this strategy be available to sites for login.", + "admin.auth.vendor": "Vendor", + "admin.auth.vendorWebsite": "Website", + "admin.auth.status": "Status" } diff --git a/ux/src/pages/AdminAuth.vue b/ux/src/pages/AdminAuth.vue index a309754d..9064bd5d 100644 --- a/ux/src/pages/AdminAuth.vue +++ b/ux/src/pages/AdminAuth.vue @@ -33,11 +33,11 @@ q-page.admin-mail dark ) q-item( - v-for='str of state.activeStrategies' + v-for='str of combinedActiveStrategies' :key='str.key' active-class='bg-primary text-white' - :active='state.selectedStrategy === str.key' - @click='state.selectedStrategy = str.key' + :active='state.selectedStrategy === str.id' + @click='state.selectedStrategy = str.id' clickable ) q-item-section(side) @@ -54,54 +54,159 @@ q-page.admin-mail icon='las la-plus' :label='t(`admin.auth.addStrategy`)' ) - q-menu(auto-close) - q-list(style='min-width: 350px;') - q-item(clickable) - .col Doude + q-menu(auto-close, fit, max-width='300px') + q-list(separator) + q-item( + v-for='str of availableStrategies' + :key='str.key' + clickable + @click='addStrategy(str)' + ) + q-item-section(avatar) + q-avatar( + rounded + color='dark' + text-color='white' + ) + q-icon( + :name='`img:` + str.icon' + ) + q-item-section + q-item-label: strong {{str.title}} + q-item-label(caption, lines='2') {{str.description}} + .col + q-card.shadow-1.q-pb-sm + q-card-section + .text-subtitle1 {{t('admin.storage.contentTypes')}} + .text-body2.text-grey {{ t('admin.storage.contentTypesHint') }} - //- v-flex(lg3, xs12) - //- v-card.animated.fadeInUp - //- v-toolbar(flat, color='teal', dark, dense) - //- .subtitle-1 {{$t('admin.auth.activeStrategies')}} - //- v-list(two-line, dense).py-0 - //- draggable( - //- v-model='activeStrategies' - //- handle='.is-handle' - //- direction='vertical' - //- ) - //- transition-group - //- v-list-item( - //- v-for='(str, idx) in activeStrategies' - //- :key='str.key' - //- @click='selectedStrategy = str.key' - //- :class='selectedStrategy === str.key ? ($vuetify.theme.dark ? `grey darken-5` : `teal lighten-5`) : ``' - //- ) - //- v-list-item-avatar.is-handle(size='24') - //- v-icon(:color='selectedStrategy === str.key ? `teal` : `grey`') mdi-drag-horizontal - //- v-list-item-content - //- v-list-item-title.body-2(:class='selectedStrategy === str.key ? `teal--text` : ``') {{ str.displayName }} - //- v-list-item-subtitle: .caption(:class='selectedStrategy === str.key ? `teal--text ` : ``') {{ str.strategy.title }} - //- v-list-item-avatar(v-if='selectedStrategy === str.key', size='24') - //- v-icon.animated.fadeInLeft(color='teal', large) mdi-chevron-right - //- v-card-chin - //- v-menu(offset-y, bottom, min-width='250px', max-width='550px', max-height='50vh', style='flex: 1 1;', center) - //- template(v-slot:activator='{ on }') - //- v-btn(v-on='on', color='primary', depressed, block) - //- v-icon(left) mdi-plus - //- span {{$t('admin.auth.addStrategy')}} - //- v-list(dense) - //- template(v-for='(str, idx) of strategies') - //- v-list-item( - //- :key='str.key' - //- :disabled='str.isDisabled' - //- @click='addStrategy(str)' - //- ) - //- v-list-item-avatar(height='24', width='48', tile) - //- v-img(:src='str.logo', width='48px', height='24px', contain, :style='str.isDisabled ? `opacity: .25;` : ``') - //- v-list-item-content - //- v-list-item-title {{str.title}} - //- v-list-item-subtitle: .caption(:style='str.isDisabled ? `opacity: .4;` : ``') {{str.description}} - //- v-divider(v-if='idx < strategies.length - 1') + //- ----------------------- + //- Configuration + //- ----------------------- + q-card.shadow-1.q-pb-sm.q-mt-md + q-card-section + .text-subtitle1 {{t('admin.storage.config')}} + q-banner.q-mt-md( + v-if='!state.strategy.config || Object.keys(state.strategy.config).length < 1' + rounded + :class='$q.dark.isActive ? `bg-negative text-white` : `bg-grey-2 text-grey-7`' + ) {{t('admin.storage.noConfigOption')}} + template( + v-for='(cfg, cfgKey, idx) in state.strategy.config' + ) + template( + v-if='configIfCheck(cfg.if)' + ) + q-separator.q-my-sm(inset, v-if='idx > 0') + q-item(v-if='cfg.type === `boolean`', tag='label') + blueprint-icon(:icon='cfg.icon', :hue-rotate='cfg.readOnly ? -45 : 0') + q-item-section + q-item-label {{cfg.title}} + q-item-label(caption) {{cfg.hint}} + q-item-section(avatar) + q-toggle( + v-model='cfg.value' + color='primary' + checked-icon='las la-check' + unchecked-icon='las la-times' + :aria-label='t(`admin.general.allowComments`)' + :disable='cfg.readOnly' + ) + q-item(v-else) + blueprint-icon(:icon='cfg.icon', :hue-rotate='cfg.readOnly ? -45 : 0') + q-item-section + q-item-label {{cfg.title}} + q-item-label(caption) {{cfg.hint}} + q-item-section( + :style='cfg.type === `number` ? `flex: 0 0 150px;` : ``' + :class='{ "col-auto": cfg.enum && cfg.enumDisplay === `buttons` }' + ) + q-btn-toggle( + v-if='cfg.enum && cfg.enumDisplay === `buttons`' + v-model='cfg.value' + push + glossy + no-caps + toggle-color='primary' + :options='cfg.enum' + :disable='cfg.readOnly' + ) + q-select( + v-else-if='cfg.enum' + outlined + v-model='cfg.value' + :options='cfg.enum' + emit-value + map-options + dense + options-dense + :aria-label='cfg.title' + :disable='cfg.readOnly' + ) + q-input( + v-else + outlined + v-model='cfg.value' + dense + :type='cfg.multiline ? `textarea` : `input`' + :aria-label='cfg.title' + :disable='cfg.readOnly' + ) + + .col-auto(v-if='state.selectedStrategy && state.strategy') + //- ----------------------- + //- Infobox + //- ----------------------- + q-card.rounded-borders.q-pb-md(style='width: 350px;') + q-card-section + .text-subtitle1 {{state.strategy.strategy.title}} + q-img.q-mt-sm.rounded-borders( + :src='state.strategy.strategy.logo' + fit='cover' + no-spinner + ) + .text-body2.q-mt-md {{state.strategy.strategy.description}} + q-separator.q-mb-sm(inset) + q-item + q-item-section + q-item-label.text-grey {{t(`admin.auth.vendor`)}} + q-item-label {{state.strategy.strategy.vendor}} + q-separator.q-my-sm(inset) + q-item + q-item-section + q-item-label.text-grey {{t(`admin.auth.vendorWebsite`)}} + q-item-label: a(:href='state.strategy.strategy.website', target='_blank', rel='noreferrer') {{state.strategy.strategy.website}} + + //- ----------------------- + //- Status + //- ----------------------- + q-card.rounded-borders.q-pb-md.q-mt-md(style='width: 350px;') + q-card-section + .text-subtitle1 {{t(`admin.auth.status`)}} + q-item(tag='label') + q-item-section + q-item-label {{t(`admin.auth.enabled`)}} + q-item-label(caption) {{t(`admin.auth.enabledHint`)}} + q-item-label.text-deep-orange(v-if='state.strategy.strategy.key === `local`', caption) {{t(`admin.auth.enabledForced`)}} + q-item-section(avatar) + q-toggle( + v-model='state.strategy.isEnabled' + :disable='state.strategy.strategy.key === `local`' + color='primary' + checked-icon='las la-check' + unchecked-icon='las la-times' + :aria-label='t(`admin.auth.enabled`)' + ) + q-separator.q-my-sm(inset) + q-item + q-item-section + q-btn.acrylic-btn( + icon='las la-trash-alt' + flat + color='negative' + :disable='state.strategy.strategy.key === `local`' + label='Delete Strategy' + ) //- v-flex(xs12, lg9) //- v-card.animated.fadeInUp.wait-p2s @@ -263,7 +368,7 @@ q-page.admin-mail diff --git a/ux/src/pages/AdminStorage.vue b/ux/src/pages/AdminStorage.vue index 81d7b8ae..74ce923a 100644 --- a/ux/src/pages/AdminStorage.vue +++ b/ux/src/pages/AdminStorage.vue @@ -438,7 +438,7 @@ q-page.admin-storage //- ----------------------- q-card.rounded-borders.q-pb-md.q-mt-md(style='width: 350px;') q-card-section - .text-subtitle1 Status + .text-subtitle1 {{ t('admin.storage.status') }} template(v-if='state.target.module !== `db` && !(state.target.setup && state.target.setup.handler && state.target.setup.state !== `configured`)') q-item(tag='label') q-item-section @@ -452,7 +452,7 @@ q-page.admin-storage color='primary' checked-icon='las la-check' unchecked-icon='las la-times' - :aria-label='t(`admin.general.allowSearch`)' + :aria-label='t(`admin.storage.enabled`)' ) q-separator.q-my-sm(inset) q-item