diff --git a/build.gradle b/build.gradle index 485109779..aa0d53658 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,7 @@ dependencies { include "com.enonic.xp:lib-io:${xpVersion}" include "com.enonic.lib:lib-admin-ui:${libAdminUiVersion}" devResources "com.enonic.lib:lib-admin-ui:${libAdminUiVersion}" - include "com.enonic.lib:lib-graphql:2.0.1" + include "com.enonic.lib:lib-graphql:2.1.0" include "com.enonic.lib:lib-mustache:2.1.0" include 'com.enonic.lib:lib-router:3.1.0' include 'com.enonic.lib:lib-static:1.0.3' diff --git a/package-lock.json b/package-lock.json index 5b4871a72..2e28e8b75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,10 @@ "devDependencies": { "@enonic-types/global": "^7.13.2", "@enonic-types/lib-admin": "^7.13.2", + "@enonic-types/lib-auth": "^7.13.2", "@enonic-types/lib-i18n": "^7.13.2", "@enonic-types/lib-io": "^7.13.2", + "@enonic-types/lib-node": "^7.13.2", "@enonic-types/lib-portal": "^7.13.2", "@enonic/esbuild-plugin-copy-with-hash": "^0.0.1", "@enonic/eslint-config": "^1.2.0", @@ -309,6 +311,21 @@ "integrity": "sha512-UA62DOCN5x7Jj4F8MxDpa6l+7GfkZI0O59xvoT5BfJF8JGoKWbhaUadRZsMJiaDhKkQUMjcPLF4bD3FZVGkuPA==", "dev": true }, + "node_modules/@enonic-types/lib-auth": { + "version": "7.13.3", + "resolved": "https://registry.npmjs.org/@enonic-types/lib-auth/-/lib-auth-7.13.3.tgz", + "integrity": "sha512-HEme70wCpzqpfWGi2DSMffq2KDKI+u8QJLAeu1k+g49RFWwYcdtC0AXdvu0GN4dzIW/2ITs72JFLW/fAMXM+tw==", + "dev": true, + "dependencies": { + "@enonic-types/core": "7.13.3" + } + }, + "node_modules/@enonic-types/lib-auth/node_modules/@enonic-types/core": { + "version": "7.13.3", + "resolved": "https://registry.npmjs.org/@enonic-types/core/-/core-7.13.3.tgz", + "integrity": "sha512-wi4mNgs+6Pyhs/Zik0NVmPecNjlSR3JvgzHeglGReDVhiEzwQkMvFKx83rO/0HR5+WBX8b4YVlms8i5020E1HQ==", + "dev": true + }, "node_modules/@enonic-types/lib-i18n": { "version": "7.13.3", "resolved": "https://registry.npmjs.org/@enonic-types/lib-i18n/-/lib-i18n-7.13.3.tgz", @@ -324,6 +341,21 @@ "@enonic-types/core": "7.13.3" } }, + "node_modules/@enonic-types/lib-node": { + "version": "7.13.3", + "resolved": "https://registry.npmjs.org/@enonic-types/lib-node/-/lib-node-7.13.3.tgz", + "integrity": "sha512-uyT5S2bbHrWPYOejVyOSaCDyc9QVW/4sG1A9jXVj57KEN5ZvokkRUPz2RSXHQLgg7wCT+Vl8aqDWUPeyUzpw1g==", + "dev": true, + "dependencies": { + "@enonic-types/core": "7.13.3" + } + }, + "node_modules/@enonic-types/lib-node/node_modules/@enonic-types/core": { + "version": "7.13.3", + "resolved": "https://registry.npmjs.org/@enonic-types/core/-/core-7.13.3.tgz", + "integrity": "sha512-wi4mNgs+6Pyhs/Zik0NVmPecNjlSR3JvgzHeglGReDVhiEzwQkMvFKx83rO/0HR5+WBX8b4YVlms8i5020E1HQ==", + "dev": true + }, "node_modules/@enonic-types/lib-portal": { "version": "7.13.3", "resolved": "https://registry.npmjs.org/@enonic-types/lib-portal/-/lib-portal-7.13.3.tgz", diff --git a/package.json b/package.json index b4e8c0eb9..65b6e76b4 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,10 @@ "devDependencies": { "@enonic-types/global": "^7.13.2", "@enonic-types/lib-admin": "^7.13.2", + "@enonic-types/lib-auth": "^7.13.2", "@enonic-types/lib-i18n": "^7.13.2", "@enonic-types/lib-io": "^7.13.2", + "@enonic-types/lib-node": "^7.13.2", "@enonic-types/lib-portal": "^7.13.2", "@enonic/esbuild-plugin-copy-with-hash": "^0.0.1", "@enonic/eslint-config": "^1.2.0", diff --git a/src/main/resources/lib/auth.js b/src/main/resources/lib/auth.ts similarity index 89% rename from src/main/resources/lib/auth.js rename to src/main/resources/lib/auth.ts index 7d72e56d3..b3ee954cf 100644 --- a/src/main/resources/lib/auth.js +++ b/src/main/resources/lib/auth.ts @@ -1,6 +1,6 @@ -var authLib = require('/lib/xp/auth'); +import { hasRole } from '/lib/xp/auth'; -var Roles = { +const Roles = { ADMIN: 'system.admin', EVERYONE: 'system.everyone', AUTHENTICATED: 'system.authenticated', @@ -31,7 +31,7 @@ function nullOrValue(value) { * @param {string} params.key IdProvider key. * @returns {object} the id provider specified, or null if it doesn't exist. */ -exports.getIdProvider = function (params) { +export function getIdProvider(params) { var bean = __.newBean('com.enonic.xp.app.users.lib.auth.GetIdProviderHandler'); bean.setIdProviderKey(required(params, 'key')); return __.toNativeObject(bean.getIdProvider()); @@ -42,7 +42,7 @@ exports.getIdProvider = function (params) { * * @returns {object[]} Array of id providers. */ -exports.getIdProviders = function () { +export function getIdProviders() { var bean = __.newBean('com.enonic.xp.app.users.lib.auth.GetIdProvidersHandler'); return __.toNativeObject(bean.getIdProviders()); }; @@ -54,7 +54,7 @@ exports.getIdProviders = function () { * @param {string} params.key Application key of the ID Provider application. * @returns {string} The ID provider mode. */ -exports.getIdProviderMode = function (params) { +export function getIdProviderMode(params) { var bean = __.newBean('com.enonic.xp.app.users.lib.auth.GetIdProviderModeHandler'); bean.setApplicationKey(required(params, 'key')); return bean.getIdProviderMode(); @@ -67,7 +67,7 @@ exports.getIdProviderMode = function (params) { * @param {string} params.key Key of the id provider to fetch permissions for. * @returns {object[]} Returns the list of principals with access level. */ -exports.getPermissions = function (params) { +export function getPermissions(params) { var bean = __.newBean('com.enonic.xp.app.users.lib.auth.GetPermissionsHandler'); bean.setIdProviderKey(required(params, 'key')); return __.toNativeObject(bean.getPermissions()); @@ -78,7 +78,7 @@ exports.getPermissions = function (params) { * * @returns {object[]} Returns the list of principals with access level. */ -exports.defaultPermissions = function () { +export function defaultPermissions() { var bean = __.newBean('com.enonic.xp.app.users.lib.auth.DefaultPermissionsHandler'); return __.toNativeObject(bean.defaultPermissions()); }; @@ -92,7 +92,7 @@ exports.defaultPermissions = function () { * @param {object} [params.idProviderConfig] ID Provider configuration. * @param {object} [params.permissions] Id provider permissions. */ -exports.createIdProvider = function (params) { +export function createIdProvider(params) { var bean = __.newBean('com.enonic.xp.app.users.lib.auth.CreateIdProviderHandler'); bean.setName(required(params, 'name')); @@ -113,7 +113,7 @@ exports.createIdProvider = function (params) { * @param {object} [params.permissions] Id provider permissions. * @returns {object} The updated id provider. */ -exports.modifyIdProvider = function (params) { +export function modifyIdProvider(params) { var bean = __.newBean('com.enonic.xp.app.users.lib.auth.ModifyIdProviderHandler'); bean.setIdProviderKey(required(params, 'key')); @@ -130,12 +130,12 @@ exports.modifyIdProvider = function (params) { * @param {string} params.keys Array of id provider keys to delete. * @returns {object} the id providers specified, or null if it doesn't exist. */ -exports.deleteIdProviders = function (params) { +export function deleteIdProviders(params) { var bean = __.newBean('com.enonic.xp.app.users.lib.auth.DeleteIdProvidersHandler'); bean.setIdProviderKeys(__.toScriptValue(required(params, 'keys'))); return __.toNativeObject(bean.deleteIdProviders()); }; -exports.isAdmin = function() { - return authLib.hasRole(Roles.ADMIN); +export function isAdmin() { + return hasRole(Roles.ADMIN); }; diff --git a/src/main/resources/lib/common.js b/src/main/resources/lib/common.ts similarity index 68% rename from src/main/resources/lib/common.js rename to src/main/resources/lib/common.ts index a6ad1a82c..dc90e1f4a 100644 --- a/src/main/resources/lib/common.js +++ b/src/main/resources/lib/common.ts @@ -1,50 +1,49 @@ -var nodeLib = require('/lib/xp/node'); -var namePrettyfier = Java.type('com.enonic.xp.name.NamePrettyfier'); +import { connect } from '/lib/xp/node'; -var REPO_NAME = 'system-repo'; -var REPO_BRANCH = 'master'; -var MAX_COUNT = -1; -var SYSTEM_ADMIN = 'role:system.admin'; +const namePrettyfier = Java.type('com.enonic.xp.name.NamePrettyfier'); -var UserItemType = exports.UserItemType = { +const REPO_NAME = 'system-repo'; +const REPO_BRANCH = 'master'; +const MAX_COUNT = -1; +const SYSTEM_ADMIN = 'role:system.admin'; + +export const UserItemType = { ROLE: 'ROLE', USER: 'USER', GROUP: 'GROUP', - ID_PROVIDER: 'ID_PROVIDER' -}; -exports.UserItemType.all = function () { - return [ - UserItemType.ROLE, - UserItemType.USER, - UserItemType.GROUP, - UserItemType.ID_PROVIDER - ]; + ID_PROVIDER: 'ID_PROVIDER', + all: () => { + return [ + UserItemType.ROLE, + UserItemType.USER, + UserItemType.GROUP, + UserItemType.ID_PROVIDER + ]; + } }; -var PrincipalType = exports.PrincipalType = { +export const PrincipalType = { ROLE: 'ROLE', USER: 'USER', - GROUP: 'GROUP' -}; -exports.PrincipalType.all = function () { - return [PrincipalType.ROLE, PrincipalType.USER, PrincipalType.GROUP]; + GROUP: 'GROUP', + all: () => { + return [PrincipalType.ROLE, PrincipalType.USER, PrincipalType.GROUP]; + } }; -exports.singleOrArray = function (value) { +export function singleOrArray(value) { return value && value.length === 1 ? value[0] : value; }; -function isString(str) { +export function isString(str) { return (typeof str === 'string') || (str instanceof String); } -exports.isString = isString; - -exports.refresh = function (repo) { +export function refresh(repo) { newConnection(repo).refresh('SEARCH'); }; -exports.required = function (params, name, skipTrimming) { +export function required(params, name, skipTrimming?: boolean) { var value = params[name]; if (value === undefined || value === null) { throw new Error("Parameter '" + name + "' is required"); @@ -55,7 +54,7 @@ exports.required = function (params, name, skipTrimming) { return value; }; -exports.default = function (params, name, defaultValue) { +export default function(params, name, defaultValue) { var value = params[name]; if (value === undefined || value === null) { return defaultValue; @@ -63,15 +62,16 @@ exports.default = function (params, name, defaultValue) { return value; }; -exports.getByIds = function (ids, repo) { +export function getByIds(ids, repo?: string) { return newConnection(repo).get(ids); }; -exports.delete = function (ids, repo) { +function _delete(ids, repo) { return newConnection(repo).delete(ids); -}; +} +export { _delete as delete }; -exports.keysToPaths = function (keys) { +export function keysToPaths(keys) { return keys.map(function (key) { if (isIdProvider(key)) { return '/identity/' + idProviderFromKey(key); @@ -99,27 +99,27 @@ exports.keysToPaths = function (keys) { }); }; -exports.isUser = function isUser(key) { - return exports.typeFromKey(key).toUpperCase() === PrincipalType.USER; +export function isUser(key) { + return typeFromKey(key).toUpperCase() === PrincipalType.USER; }; -exports.isGroup = function isGroup(key) { - return exports.typeFromKey(key).toUpperCase() === PrincipalType.GROUP; +export function isGroup(key) { + return typeFromKey(key).toUpperCase() === PrincipalType.GROUP; }; -exports.isRole = function isRole(key) { - return exports.typeFromKey(key).toUpperCase() === PrincipalType.ROLE; +export function isRole(key) { + return typeFromKey(key).toUpperCase() === PrincipalType.ROLE; }; -exports.isIdProvider = function isIdProvider(key) { +export function isIdProvider(key) { return splitKey(key).length === 1; }; -exports.isSystemAdmin = function isSystemAdmin(key) { +export function isSystemAdmin(key) { return key === SYSTEM_ADMIN; } -exports.createQueryByField = function (field, values) { +export function createQueryByField(field, values) { if (!values || !field) { return null; } @@ -137,7 +137,7 @@ function serializeValue(value) { return typeof value === 'string' ? '"' + value + '"' : value; } -exports.extensionFromMimeType = function (mimeType) { +export function extensionFromMimeType (mimeType) { var ext = ''; if (mimeType.indexOf('image/png') > -1) { ext = '.png'; @@ -167,7 +167,7 @@ function splitKey(key) { return parts; } -exports.idProviderFromKey = function idProviderFromKey(key) { +export function idProviderFromKey(key) { var parts = splitKey(key); if (parts[0].toUpperCase() === PrincipalType.ROLE) { throw new Error( @@ -177,7 +177,7 @@ exports.idProviderFromKey = function idProviderFromKey(key) { return parts.length === 1 ? parts[0] : parts[1]; }; -exports.nameFromKey = function nameFromKey(key) { +export function nameFromKey(key) { var parts = splitKey(key); if (parts.length === 1) { throw new Error("Key don't have name [" + key + ']'); @@ -185,7 +185,7 @@ exports.nameFromKey = function nameFromKey(key) { return parts[0].toUpperCase() !== PrincipalType.ROLE ? parts[2] : parts[1]; }; -exports.typeFromKey = function typeFromKey(key) { +export function typeFromKey(key) { var parts = splitKey(key); if (parts.length === 1) { throw new Error("Key don't have type [" + key + ']'); @@ -193,11 +193,11 @@ exports.typeFromKey = function typeFromKey(key) { return parts[0]; }; -exports.prettifyName = function (text) { +export function prettifyName(text) { return namePrettyfier.create(text); }; -exports.querySingle = function (query, repo) { +export function querySingle(query, repo) { var results = queryAll({ start: 0, count: 1, @@ -207,15 +207,15 @@ exports.querySingle = function (query, repo) { return results.total === 1 ? results.hits[0] : null; }; -exports.create = function (params, repo) { +export function create(params, repo) { return newConnection(repo).create(params); }; -exports.update = function (params, repo) { +export function update(params, repo) { return newConnection(repo).modify(params); }; -exports.queryAll = function queryAll(params, repo) { +export function queryAll(params, repo?: string) { var start = params.start || 0; var count = params.count == null ? MAX_COUNT : params.count; @@ -245,11 +245,9 @@ exports.queryAll = function queryAll(params, repo) { }; }; -function newConnection(repo, branch) { - return nodeLib.connect({ +export function newConnection(repo: string, branch?: string) { + return connect({ repoId: repo || REPO_NAME, branch: branch || REPO_BRANCH }); } - -exports.newConnection = newConnection; diff --git a/src/main/resources/lib/groups.js b/src/main/resources/lib/groups.ts similarity index 100% rename from src/main/resources/lib/groups.js rename to src/main/resources/lib/groups.ts diff --git a/src/main/resources/lib/idproviders.js b/src/main/resources/lib/idproviders.js deleted file mode 100644 index a559cd9ea..000000000 --- a/src/main/resources/lib/idproviders.js +++ /dev/null @@ -1,52 +0,0 @@ -var common = require('./common'); -var authLib = require('./auth'); - -var DEFAULT_KEY = 'default'; - -module.exports = { - getByKey: function(key) { - return authLib.getIdProvider({key: key}); - }, - list: authLib.getIdProviders, - getDefault: function () { - return {key: 'default'}; - }, - create: function(params) { - var name = common.required(params, 'key'); - - return authLib.createIdProvider({ - name: common.prettifyName(name), - displayName: params.displayName, - description: params.description, - idProviderConfig: params.idProviderConfig, - permissions: params.permissions || [] - }); - }, - update: function(params) { - var key = common.required(params, 'key'); - - return authLib.modifyIdProvider({ - key: key, - editor: function (idProvider) { - var newIdProvider = idProvider; - newIdProvider.displayName = params.displayName; - newIdProvider.description = params.description; - newIdProvider.idProviderConfig = params.idProviderConfig; - return newIdProvider; - }, - permissions: params.permissions || [] - }); - }, - delete: function(keys) { - return authLib.deleteIdProviders({keys: keys}); - }, - getIdProviderMode: function(applicationKey) { - return authLib.getIdProviderMode({key:applicationKey}); - }, - getPermissions: function(key) { - if (key === DEFAULT_KEY) { - return authLib.defaultPermissions(); - } - return authLib.getPermissions({key: key}); - } -}; diff --git a/src/main/resources/lib/idproviders.ts b/src/main/resources/lib/idproviders.ts new file mode 100644 index 000000000..5d242175e --- /dev/null +++ b/src/main/resources/lib/idproviders.ts @@ -0,0 +1,70 @@ +import { + prettifyName, + required +} from './common'; +import { + createIdProvider, + defaultPermissions, + deleteIdProviders, + getIdProvider, + getIdProviderMode as _getIdProviderMode, + getIdProviders, + getPermissions as _getPermissions, + modifyIdProvider +} from './auth'; + +const DEFAULT_KEY = 'default'; + +export function getByKey(key) { + return getIdProvider({key: key}); +} + +export const list = getIdProviders; + +export function getDefault() { + return {key: 'default'}; +} + +export function create(params) { + var name = required(params, 'key'); + + return createIdProvider({ + name: prettifyName(name), + displayName: params.displayName, + description: params.description, + idProviderConfig: params.idProviderConfig, + permissions: params.permissions || [] + }); +} + +export function update(params) { + var key = required(params, 'key'); + + return modifyIdProvider({ + key: key, + editor: function (idProvider) { + var newIdProvider = idProvider; + newIdProvider.displayName = params.displayName; + newIdProvider.description = params.description; + newIdProvider.idProviderConfig = params.idProviderConfig; + return newIdProvider; + }, + permissions: params.permissions || [] + }); +} + +function _delete(keys) { + return deleteIdProviders({keys: keys}); +} +export { _delete as delete }; + +export function getIdProviderMode(applicationKey) { + return _getIdProviderMode({key:applicationKey}); +} + +export function getPermissions(key) { + if (key === DEFAULT_KEY) { + return defaultPermissions(); + } + return _getPermissions({key: key}); +} diff --git a/src/main/resources/lib/permissionReports.js b/src/main/resources/lib/permissionReports.ts similarity index 100% rename from src/main/resources/lib/permissionReports.js rename to src/main/resources/lib/permissionReports.ts diff --git a/src/main/resources/lib/principals.js b/src/main/resources/lib/principals.js deleted file mode 100644 index dab3adc72..000000000 --- a/src/main/resources/lib/principals.js +++ /dev/null @@ -1,154 +0,0 @@ -var common = require('./common'); -var authLib = require('/lib/xp/auth'); - -module.exports = { - getByKeys: function (keys) { - var noKeys = keys == null || (keys instanceof Array && keys.length === 0); - - // users and groups have their keys as _id, but roles have them stored as key - var principals = noKeys ? [] : common.queryAll({ - query: - common.createQueryByField('_id', keys) + - ' OR ' + - common.createQueryByField('key', keys) - }).hits; - - return keys instanceof Array ? principals : common.singleOrArray(principals); - }, - getMemberships: function (key, transitive) { - return authLib.getMemberships(key, transitive); - }, - addMemberships: function(key, memberships) { - var addMms = [].concat(memberships).map(function(current) { - module.exports.addMembers(current, key); - return current; - }); - return addMms; - }, - removeMemberships: function(key, memberships) { - var removeMms = [].concat(memberships).map(function(current) { - module.exports.removeMembers(current, key); - return current; - }); - return removeMms; - }, - updateMemberships: function(key, addMms, removeMms) { - if (addMms && addMms.length > 0) { - module.exports.addMemberships(key, addMms); - } - if (removeMms && removeMms.length > 0) { - module.exports.removeMemberships(key, removeMms); - } - }, - getMembers: function(key) { - return authLib.getMembers(key); - }, - addMembers: function(key, members) { - try { - authLib.addMembers(key, members); - } catch (e) { - log.error( - 'Could not add members ' + - JSON.stringify(members) + - ' to [' + - key + - ']', - e - ); - } - return members; - }, - removeMembers: function(key, members) { - try { - authLib.removeMembers(key, members); - } catch (e) { - log.error( - 'Could not remove members ' + - JSON.stringify(members) + - ' from [' + - key + - ']', - e - ); - } - return members; - }, - updateMembers: function(key, addMs, removeMs) { - if (addMs && addMs.length > 0) { - module.exports.addMembers(key, addMs); - } - if (removeMs && removeMs.length > 0) { - module.exports.removeMembers(key, removeMs); - } - }, - list: function (idProviderKey, types, query, start, count, sort) { - return common.queryAll({ - query: createPrincipalQuery(idProviderKey, types, query), - start: start, - count: count, - sort: sort - }); - }, - delete: function(keys) { - return keys.map(function(key) { - try { - var deleted = authLib.deletePrincipal(key); - return { - key: key, - deleted: deleted, - reason: deleted ? '' : 'Principal [' + key + '] could not be deleted' - }; - } catch (e) { - return { - key: key, - deleted: false, - reason: e.message - }; - } - }); - }, - Type: common.PrincipalType -}; - -function createPrincipalQuery(idProviderKey, types, query) { - var q = query ? textQuery(query) : ''; - if (!types) { - q += (q ? ' AND ' : '') + idProviderQuery(idProviderKey); - } else { - var tq = ''; - types.forEach(function(type, index) { - var add; - switch (type) { - case common.PrincipalType.ROLE: - add = rolesQuery(); - break; - case common.PrincipalType.GROUP: - case common.PrincipalType.USER: - add = idProviderQuery(idProviderKey, type); - break; - default: // none - } - tq += (index > 0 ? ' OR ' : '') + add; - }); - q += q ? ' AND (' + tq + ')' : tq; - } - return q; -} - -function textQuery(query) { - var q = '"_allText,displayName","' + query + '","AND"'; - return '(fulltext(' + q + ') OR ngram(' + q + '))'; -} - -function rolesQuery() { - return '_parentPath="/identity/roles"'; -} - -function idProviderQuery(key, type) { - return ( - '(userStoreKey="' + - key + - '"' + - (type ? 'AND principalType="' + type + '")' : ')') - ); -} diff --git a/src/main/resources/lib/principals.ts b/src/main/resources/lib/principals.ts new file mode 100644 index 000000000..29fab26da --- /dev/null +++ b/src/main/resources/lib/principals.ts @@ -0,0 +1,171 @@ +import { + createQueryByField, + PrincipalType, + queryAll, + singleOrArray +} from './common'; +import { deletePrincipal } from '/lib/xp/auth'; + + +export function getByKeys(keys) { + var noKeys = keys == null || (keys instanceof Array && keys.length === 0); + + // users and groups have their keys as _id, but roles have them stored as key + var principals = noKeys ? [] : queryAll({ + query: + createQueryByField('_id', keys) + + ' OR ' + + createQueryByField('key', keys) + }).hits; + + return keys instanceof Array ? principals : singleOrArray(principals); +} + +export function getMemberships(key, transitive) { + return authLib.getMemberships(key, transitive); +} + +export function addMemberships(key, memberships) { + var addMms = [].concat(memberships).map(function(current) { + addMembers(current, key); + return current; + }); + return addMms; +} + +export function removeMemberships(key, memberships) { + var removeMms = [].concat(memberships).map(function(current) { + removeMembers(current, key); + return current; + }); + return removeMms; +} + +export function updateMemberships(key, addMms, removeMms) { + if (addMms && addMms.length > 0) { + addMemberships(key, addMms); + } + if (removeMms && removeMms.length > 0) { + removeMemberships(key, removeMms); + } +} + +export function getMembers(key) { + return authLib.getMembers(key); +} + +export function addMembers(key, members) { + try { + authLib.addMembers(key, members); + } catch (e) { + log.error( + 'Could not add members ' + + JSON.stringify(members) + + ' to [' + + key + + ']', + e + ); + } + return members; +} + +export function removeMembers(key, members) { + try { + authLib.removeMembers(key, members); + } catch (e) { + log.error( + 'Could not remove members ' + + JSON.stringify(members) + + ' from [' + + key + + ']', + e + ); + } + return members; +} + +export function updateMembers(key, addMs, removeMs) { + if (addMs && addMs.length > 0) { + addMembers(key, addMs); + } + if (removeMs && removeMs.length > 0) { + removeMembers(key, removeMs); + } +} + +export function list(idProviderKey, types, query, start, count, sort) { + return queryAll({ + query: createPrincipalQuery(idProviderKey, types, query), + start: start, + count: count, + sort: sort + }); +} + +function _delete(keys) { + return keys.map(function(key) { + try { + var deleted = deletePrincipal(key); + return { + key: key, + deleted: deleted, + reason: deleted ? '' : 'Principal [' + key + '] could not be deleted' + }; + } catch (e) { + return { + key: key, + deleted: false, + reason: e.message + }; + } + }); +} +export { _delete as delete }; + +export const Type = PrincipalType; + + +function createPrincipalQuery(idProviderKey, types, query) { + var q = query ? textQuery(query) : ''; + if (!types) { + q += (q ? ' AND ' : '') + idProviderQuery(idProviderKey); + } else { + var tq = ''; + types.forEach(function(type, index) { + var add; + switch (type) { + case PrincipalType.ROLE: + add = rolesQuery(); + break; + case PrincipalType.GROUP: + case PrincipalType.USER: + add = idProviderQuery(idProviderKey, type); + break; + default: // none + } + tq += (index > 0 ? ' OR ' : '') + add; + }); + q += q ? ' AND (' + tq + ')' : tq; + } + return q; +} + +function textQuery(query) { + var q = '"_allText,displayName","' + query + '","AND"'; + return '(fulltext(' + q + ') OR ngram(' + q + '))'; +} + +function rolesQuery() { + return '_parentPath="/identity/roles"'; +} + +function idProviderQuery(key, type?: string) { + return ( + '(userStoreKey="' + + key + + '"' + + (type ? 'AND principalType="' + type + '")' : ')') + ); +} diff --git a/src/main/resources/lib/repositories.js b/src/main/resources/lib/repositories.ts similarity index 59% rename from src/main/resources/lib/repositories.js rename to src/main/resources/lib/repositories.ts index ef24d07a6..4db60a2bf 100644 --- a/src/main/resources/lib/repositories.js +++ b/src/main/resources/lib/repositories.ts @@ -1,11 +1,14 @@ -var common = require('./common'); +import { + getByIds, + queryAll +} from './common'; -exports.getById = function (id) { - return common.getByIds(id) +export function getById(id) { + return getByIds(id); }; -exports.list = function (search, start, count, sort) { - var queryResult = common.queryAll({ +export function list(search, start, count, sort) { + var queryResult = queryAll({ query: createRepoQuery(search), start: start, count: count, diff --git a/src/main/resources/lib/roles.js b/src/main/resources/lib/roles.ts similarity index 100% rename from src/main/resources/lib/roles.js rename to src/main/resources/lib/roles.ts diff --git a/src/main/resources/lib/useritems.js b/src/main/resources/lib/useritems.ts similarity index 100% rename from src/main/resources/lib/useritems.js rename to src/main/resources/lib/useritems.ts diff --git a/src/main/resources/lib/users.js b/src/main/resources/lib/users.ts similarity index 100% rename from src/main/resources/lib/users.js rename to src/main/resources/lib/users.ts diff --git a/src/main/resources/lib/util.js b/src/main/resources/lib/util.ts similarity index 100% rename from src/main/resources/lib/util.js rename to src/main/resources/lib/util.ts diff --git a/src/main/resources/services/config/config.js b/src/main/resources/services/config/config.js deleted file mode 100644 index 2663a326a..000000000 --- a/src/main/resources/services/config/config.js +++ /dev/null @@ -1,27 +0,0 @@ -/*global app, require*/ - -var admin = require('/lib/xp/admin'); -var portal = require('/lib/xp/portal'); - -function handleGet() { - return { - status: 200, - contentType: 'application/json', - body: { - adminUrl: admin.getBaseUri(), - appId: app.name, - assetsUri: portal.assetUrl({path: ''}), - toolUri: admin.getToolUrl( - app.name, - 'main' - ), - services: { - graphQlUrl: portal.serviceUrl({ service: 'graphql'}), - reportServiceUrl: portal.serviceUrl({service: 'permissionReport'}), - i18nUrl: portal.serviceUrl({service: 'i18n'}), - } - } - }; -} - -exports.get = handleGet; diff --git a/src/main/resources/services/config/config.ts b/src/main/resources/services/config/config.ts new file mode 100644 index 000000000..4a3bdc9e8 --- /dev/null +++ b/src/main/resources/services/config/config.ts @@ -0,0 +1,30 @@ +import { + getBaseUri, + getToolUrl +} from '/lib/xp/admin'; +import { + assetUrl, + serviceUrl +} from '/lib/xp/portal'; + + +export function get() { + return { + status: 200, + contentType: 'application/json', + body: { + adminUrl: getBaseUri(), + appId: app.name, + assetsUri: assetUrl({ path: '' }), + toolUri: getToolUrl( + app.name, + 'main' + ), + services: { + graphQlUrl: serviceUrl({ service: 'graphql' }), + reportServiceUrl: serviceUrl({ service: 'permissionReport' }), + i18nUrl: serviceUrl({ service: 'i18n' }), + } + } + }; +} diff --git a/src/main/resources/services/graphql/graphql.js b/src/main/resources/services/graphql/graphql.js deleted file mode 100644 index b840e982c..000000000 --- a/src/main/resources/services/graphql/graphql.js +++ /dev/null @@ -1,23 +0,0 @@ -//TODO Remove GraphQLSchemaSynchronizer for Enonic XP 6.13 - -var graphQl = require('/lib/graphql'); -var schemaGenerator = require('./schemaUtil').schemaGenerator; - -Java.type('com.enonic.xp.app.users.GraphQLSchemaSynchronizer').sync(__.toScriptValue(function() { - var graphQlSchema = require('./schema'); - var schema = schemaGenerator.createSchema(graphQlSchema); - - exports.post = function(req) { - var body = JSON.parse(req.body); - var operation = body.query || body.mutation; - if (!operation) { - throw new Error('`query` or `mutation` param is missing.'); - } - var result = graphQl.execute(schema, operation, body.variables); - return { - contentType: 'application/json', - body: result - }; - }; -})); - diff --git a/src/main/resources/services/graphql/graphql.ts b/src/main/resources/services/graphql/graphql.ts new file mode 100644 index 000000000..877b3c3ae --- /dev/null +++ b/src/main/resources/services/graphql/graphql.ts @@ -0,0 +1,23 @@ +//TODO Remove GraphQLSchemaSynchronizer for Enonic XP 6.13 + +// @ts-expect-error Cannot find module '/lib/graphql' or its corresponding type declarations.ts(2307) +import { execute } from '/lib/graphql'; +import { schemaGenerator } from './schemaUtil'; + +Java.type('com.enonic.xp.app.users.GraphQLSchemaSynchronizer').sync(__.toScriptValue(function() { + var graphQlSchema = require('./schema'); + var schema = schemaGenerator.createSchema(graphQlSchema); +})); + +export function post(req) { + var body = JSON.parse(req.body); + var operation = body.query || body.mutation; + if (!operation) { + throw new Error('`query` or `mutation` param is missing.'); + } + var result = execute(schema, operation, body.variables); + return { + contentType: 'application/json', + body: result + }; +}; diff --git a/src/main/resources/services/graphql/schema/index.js b/src/main/resources/services/graphql/schema/index.ts similarity index 100% rename from src/main/resources/services/graphql/schema/index.js rename to src/main/resources/services/graphql/schema/index.ts diff --git a/src/main/resources/services/graphql/schema/mutation.js b/src/main/resources/services/graphql/schema/mutation.ts similarity index 100% rename from src/main/resources/services/graphql/schema/mutation.js rename to src/main/resources/services/graphql/schema/mutation.ts diff --git a/src/main/resources/services/graphql/schema/query.js b/src/main/resources/services/graphql/schema/query.ts similarity index 56% rename from src/main/resources/services/graphql/schema/query.js rename to src/main/resources/services/graphql/schema/query.ts index a507231c2..d142daa30 100644 --- a/src/main/resources/services/graphql/schema/query.js +++ b/src/main/resources/services/graphql/schema/query.ts @@ -1,15 +1,33 @@ -var graphQl = require('/lib/graphql'); -var authLib = require('/lib/auth'); +import { + GraphQLInt, + GraphQLString, + list, + nonNull + // @ts-expect-error Cannot find module '/lib/graphql' or its corresponding type declarations.ts(2307) +} from '/lib/graphql'; +import { isAdmin } from '/lib/auth'; -var idproviders = require('/lib/idproviders'); -var principals = require('/lib/principals'); +import { + getByKey, + getDefault, + list as listIdProviders +} from '/lib/idproviders'; +import { + getByKeys as getPrincipalsByKeys, + list as listPrincipals, + Type +} from '/lib/principals'; var useritems = require('/lib/useritems'); -var repositories = require('/lib/repositories'); +import { + getById as getRepositoryById, + list as listRepositories +} from '/lib/repositories'; +import { schemaGenerator } from '../schemaUtil'; +import TypesType from '../types'; -var schemaGenerator = require('../schemaUtil').schemaGenerator; -var graphQlObjectTypes = require('../types').objects; -var graphQlEnums = require('../types').enums; +var graphQlObjectTypes = TypesType.objects; +var graphQlEnums = TypesType.enums; function getUserItems(args, types) { @@ -20,49 +38,49 @@ function getUserItems(args, types) { return useritems.list(types, query, itemIds, start, count); } -module.exports = schemaGenerator.createObjectType({ +export = schemaGenerator.createObjectType({ name: 'Query', fields: { idProviders: { - type: graphQl.list(graphQlObjectTypes.IdProviderType), + type: list(graphQlObjectTypes.IdProviderType), resolve: function () { - return idproviders.list(); + return listIdProviders(); } }, idProvider: { type: graphQlObjectTypes.IdProviderType, args: { - key: graphQl.nonNull(graphQl.GraphQLString) + key: nonNull(GraphQLString) }, resolve: function (env) { var key = env.args.key; - return idproviders.getByKey(key); + return getByKey(key); } }, defaultIdProvider: { type: graphQlObjectTypes.IdProviderType, resolve: function () { - return idproviders.getDefault(); + return getDefault(); } }, principalsConnection: { type: graphQlObjectTypes.PrincipalConnectionType, args: { - idprovider: graphQl.GraphQLString, - types: graphQl.list(graphQlEnums.PrincipalTypeEnum), - query: graphQl.GraphQLString, - start: graphQl.GraphQLInt, - count: graphQl.GraphQLInt, - sort: graphQl.GraphQLString + idprovider: GraphQLString, + types: list(graphQlEnums.PrincipalTypeEnum), + query: GraphQLString, + start: GraphQLInt, + count: GraphQLInt, + sort: GraphQLString }, resolve: function (env) { var idprovider = env.args.idprovider || 'system'; - var types = env.args.types || principals.Type.all(); + var types = env.args.types || Type.all(); var query = env.args.query; var start = env.args.start; var count = env.args.count; var sort = env.args.sort; - return principals.list( + return listPrincipals( idprovider, types, query, @@ -75,31 +93,31 @@ module.exports = schemaGenerator.createObjectType({ principal: { type: graphQlObjectTypes.PrincipalType, args: { - key: graphQl.nonNull(graphQl.GraphQLString), + key: nonNull(GraphQLString), }, resolve: function (env) { var key = env.args.key; - return principals.getByKeys(key); + return getPrincipalsByKeys(key); } }, principals: { - type: graphQl.list(graphQlObjectTypes.PrincipalType), + type: list(graphQlObjectTypes.PrincipalType), args: { - keys: graphQl.nonNull(graphQl.list(graphQl.GraphQLString)) + keys: nonNull(list(GraphQLString)) }, resolve: function (env) { var keys = env.args.keys; - return principals.getByKeys(keys); + return getPrincipalsByKeys(keys); } }, userItemsConnection: { type: graphQlObjectTypes.UserItemConnectionType, args: { - types: graphQl.list(graphQlEnums.UserItemTypeEnum), - query: graphQl.GraphQLString, - itemIds: graphQl.list(graphQl.GraphQLString), - start: graphQl.GraphQLInt, - count: graphQl.GraphQLInt + types: list(graphQlEnums.UserItemTypeEnum), + query: GraphQLString, + itemIds: list(GraphQLString), + start: GraphQLInt, + count: GraphQLInt }, resolve: function (env) { return getUserItems(env.args, env.args.types); @@ -108,10 +126,10 @@ module.exports = schemaGenerator.createObjectType({ types: { type: graphQlObjectTypes.TypesType, args: { - query: graphQl.GraphQLString, - itemIds: graphQl.list(graphQl.GraphQLString), - start: graphQl.GraphQLInt, - count: graphQl.GraphQLInt + query: GraphQLString, + itemIds: list(GraphQLString), + start: GraphQLInt, + count: GraphQLInt }, resolve: function (env) { return getUserItems(env.args, null); @@ -120,33 +138,33 @@ module.exports = schemaGenerator.createObjectType({ repository: { type: graphQlObjectTypes.RepositoryType, args: { - id: graphQl.nonNull(graphQl.GraphQLString) + id: nonNull(GraphQLString) }, resolve: function (env) { - if (!authLib.isAdmin()) { + if (!isAdmin()) { throw new Error('You don\'t have permission to access this resource'); } var id = env.args.id; - return repositories.getById(id); + return getRepositoryById(id); } }, repositories: { - type: graphQl.list(graphQlObjectTypes.RepositoryType), + type: list(graphQlObjectTypes.RepositoryType), args: { - query: graphQl.GraphQLString, - start: graphQl.GraphQLInt, - count: graphQl.GraphQLInt, + query: GraphQLString, + start: GraphQLInt, + count: GraphQLInt, sort: graphQlEnums.SortModeEnum }, resolve: function (env) { - if (!authLib.isAdmin()) { + if (!isAdmin()) { throw new Error('You don\'t have permission to access this resource'); } var query = env.args.query; var start = env.args.start; var count = env.args.count; var sort = env.args.sort; - return repositories.list(query, start, count, sort); + return listRepositories(query, start, count, sort); } } } diff --git a/src/main/resources/services/graphql/schemaUtil.js b/src/main/resources/services/graphql/schemaUtil.js deleted file mode 100644 index 7218fc5d5..000000000 --- a/src/main/resources/services/graphql/schemaUtil.js +++ /dev/null @@ -1,6 +0,0 @@ -var graphqlLib = require('/lib/graphql'); - -// singleton -var schemaGenerator = graphqlLib.newSchemaGenerator(); - -exports.schemaGenerator = schemaGenerator; diff --git a/src/main/resources/services/graphql/schemaUtil.ts b/src/main/resources/services/graphql/schemaUtil.ts new file mode 100644 index 000000000..00363e271 --- /dev/null +++ b/src/main/resources/services/graphql/schemaUtil.ts @@ -0,0 +1,5 @@ +// @ts-expect-error Cannot find module '/lib/graphql' or its corresponding type declarations.ts(2307) +import { newSchemaGenerator } from '/lib/graphql'; + +// singleton +export const schemaGenerator = newSchemaGenerator(); diff --git a/src/main/resources/services/graphql/types/enums.js b/src/main/resources/services/graphql/types/enums.ts similarity index 74% rename from src/main/resources/services/graphql/types/enums.js rename to src/main/resources/services/graphql/types/enums.ts index 119aaa046..4e814d810 100644 --- a/src/main/resources/services/graphql/types/enums.js +++ b/src/main/resources/services/graphql/types/enums.ts @@ -1,6 +1,6 @@ -var schemaGenerator = require('../schemaUtil').schemaGenerator; +import { schemaGenerator } from '../schemaUtil'; -exports.IdProviderModeEnum = schemaGenerator.createEnumType({ +export const IdProviderModeEnum = schemaGenerator.createEnumType({ name: 'IdProviderMode', description: 'Enumeration of Id provider modes', values: { @@ -10,7 +10,7 @@ exports.IdProviderModeEnum = schemaGenerator.createEnumType({ } }); -exports.SortModeEnum = schemaGenerator.createEnumType({ +export const SortModeEnum = schemaGenerator.createEnumType({ name: 'SortMode', description: 'Enumeration of sort modes', values: { @@ -19,7 +19,7 @@ exports.SortModeEnum = schemaGenerator.createEnumType({ } }); -exports.UserItemTypeEnum = schemaGenerator.createEnumType({ +export const UserItemTypeEnum = schemaGenerator.createEnumType({ name: 'UserItemType', description: 'Enumeration of user item types', values: { @@ -30,7 +30,7 @@ exports.UserItemTypeEnum = schemaGenerator.createEnumType({ } }); -exports.PrincipalTypeEnum = schemaGenerator.createEnumType({ +export const PrincipalTypeEnum = schemaGenerator.createEnumType({ name: 'PrincipalType', description: 'Enumeration of principal types', values: { @@ -40,7 +40,7 @@ exports.PrincipalTypeEnum = schemaGenerator.createEnumType({ } }); -exports.PermissionEnum = schemaGenerator.createEnumType({ +export const PermissionEnum = schemaGenerator.createEnumType({ name: 'Permission', description: 'Enumeration of permissions', values: { @@ -54,7 +54,7 @@ exports.PermissionEnum = schemaGenerator.createEnumType({ } }); -exports.IdProviderAccessEnum = schemaGenerator.createEnumType({ +export const IdProviderAccessEnum = schemaGenerator.createEnumType({ name: 'IdProviderAccess', description: 'Enumeration of id provider access permissions', values: { diff --git a/src/main/resources/services/graphql/types/index.js b/src/main/resources/services/graphql/types/index.js deleted file mode 100644 index 280a1951a..000000000 --- a/src/main/resources/services/graphql/types/index.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - enums: require('./enums'), - inputs: require('./inputs'), - objects: require('./objects') -}; diff --git a/src/main/resources/services/graphql/types/index.ts b/src/main/resources/services/graphql/types/index.ts new file mode 100644 index 000000000..6d39155a2 --- /dev/null +++ b/src/main/resources/services/graphql/types/index.ts @@ -0,0 +1,6 @@ +export * as enums from './enums'; +export * as inputs from './inputs'; + +module.exports = { + objects: require('./objects') +}; diff --git a/src/main/resources/services/graphql/types/inputs.js b/src/main/resources/services/graphql/types/inputs.js deleted file mode 100644 index c86415c64..000000000 --- a/src/main/resources/services/graphql/types/inputs.js +++ /dev/null @@ -1,45 +0,0 @@ -var graphQl = require('/lib/graphql'); - -var schemaGenerator = require('../schemaUtil').schemaGenerator; - -var graphQlEnums = require('./enums'); - -// eslint-disable-next-line no-unused-vars -var PrincipalInput = schemaGenerator.createInputObjectType({ - name: 'PrincipalInput', - description: 'Input definition for principal', - fields: { - key: { - type: graphQl.nonNull(graphQl.GraphQLString) - }, - displayName: { - type: graphQl.nonNull(graphQl.GraphQLString) - } - } -}); - -exports.IdProviderAccessControlInput = schemaGenerator.createInputObjectType({ - name: 'IdProviderAccessControlInput', - description: 'Input definition for id provider access control entry', - fields: { - principal: { - type: graphQl.nonNull(graphQl.GraphQLString) - }, - access: { - type: graphQl.nonNull(graphQlEnums.IdProviderAccessEnum) - } - } -}); - -exports.IdProviderConfigInput = schemaGenerator.createInputObjectType({ - name: 'IdProviderConfigInput', - description: 'Input definition for id provider auth config', - fields: { - applicationKey: { - type: graphQl.nonNull(graphQl.GraphQLString) - }, - config: { - type: graphQl.GraphQLString - } - } -}); diff --git a/src/main/resources/services/graphql/types/inputs.ts b/src/main/resources/services/graphql/types/inputs.ts new file mode 100644 index 000000000..258ee5e2d --- /dev/null +++ b/src/main/resources/services/graphql/types/inputs.ts @@ -0,0 +1,48 @@ +import { + GraphQLString, + nonNull + // @ts-expect-error Cannot find module '/lib/graphql' or its corresponding type declarations.ts(2307) +} from '/lib/graphql'; +import { schemaGenerator } from '../schemaUtil'; +import { IdProviderAccessEnum } from './enums'; + + +// eslint-disable-next-line no-unused-vars +var PrincipalInput = schemaGenerator.createInputObjectType({ + name: 'PrincipalInput', + description: 'Input definition for principal', + fields: { + key: { + type: nonNull(GraphQLString) + }, + displayName: { + type: nonNull(GraphQLString) + } + } +}); + +export const IdProviderAccessControlInput = schemaGenerator.createInputObjectType({ + name: 'IdProviderAccessControlInput', + description: 'Input definition for id provider access control entry', + fields: { + principal: { + type: nonNull(GraphQLString) + }, + access: { + type: nonNull(IdProviderAccessEnum) + } + } +}); + +export const IdProviderConfigInput = schemaGenerator.createInputObjectType({ + name: 'IdProviderConfigInput', + description: 'Input definition for id provider auth config', + fields: { + applicationKey: { + type: nonNull(GraphQLString) + }, + config: { + type: GraphQLString + } + } +}); diff --git a/src/main/resources/services/graphql/types/objects/aggregations.js b/src/main/resources/services/graphql/types/objects/aggregations.ts similarity index 62% rename from src/main/resources/services/graphql/types/objects/aggregations.js rename to src/main/resources/services/graphql/types/objects/aggregations.ts index 5c82f491e..322461e89 100644 --- a/src/main/resources/services/graphql/types/objects/aggregations.js +++ b/src/main/resources/services/graphql/types/objects/aggregations.ts @@ -1,40 +1,44 @@ -var graphQl = require('/lib/graphql'); +import { + GraphQLInt, + GraphQLString, + list + // @ts-expect-error Cannot find module '/lib/graphql' or its corresponding type declarations.ts(2307) +} from '/lib/graphql'; +import { schemaGenerator } from '../../schemaUtil'; -var schemaGenerator = require('../../schemaUtil').schemaGenerator; var BucketType = schemaGenerator.createObjectType({ name: 'Bucket', description: 'Aggregated result for specific key', fields: { key: { - type: graphQl.GraphQLString + type: GraphQLString }, docCount: { - type: graphQl.GraphQLInt + type: GraphQLInt } } }); -var AggregationType = schemaGenerator.createObjectType({ +export const AggregationType = schemaGenerator.createObjectType({ name: 'Aggregation', description: 'List of buckets', fields: { name: { - type: graphQl.GraphQLString + type: GraphQLString }, buckets: { - type: graphQl.list(BucketType), + type: list(BucketType), resolve: function(env) { return env.source.aggregation; } } } }); -exports.AggregationType = AggregationType; -exports.createAggregationsFiled = function createAggregationsFiled() { +export function createAggregationsField() { return { - type: graphQl.list(AggregationType), + type: list(AggregationType), resolve: function(env) { var aggregations = env.source.aggregations; var aggs = []; @@ -47,4 +51,4 @@ exports.createAggregationsFiled = function createAggregationsFiled() { return aggs; } }; -}; +} diff --git a/src/main/resources/services/graphql/types/objects/connection.js b/src/main/resources/services/graphql/types/objects/connection.ts similarity index 66% rename from src/main/resources/services/graphql/types/objects/connection.js rename to src/main/resources/services/graphql/types/objects/connection.ts index 219fcf312..77f78f85e 100644 --- a/src/main/resources/services/graphql/types/objects/connection.js +++ b/src/main/resources/services/graphql/types/objects/connection.ts @@ -1,25 +1,32 @@ -var graphQl = require('/lib/graphql'); -var graphQlUtils = require('../../utils'); -var createAggregationsFiled = require('./aggregations').createAggregationsFiled; -var schemaGenerator = require('../../schemaUtil').schemaGenerator; +import { + GraphQLBoolean, + GraphQLInt, + list, + nonNull + // @ts-expect-error Cannot find module '/lib/graphql' or its corresponding type declarations.ts(2307) +} from '/lib/graphql'; +import { toInt } from '../../utils'; +import { createAggregationsField } from './aggregations'; +import { schemaGenerator } from '../../schemaUtil'; + var pageInfoType = schemaGenerator.createObjectType({ name: 'PageInfo', fields: { startCursor: { - type: graphQl.nonNull(graphQl.GraphQLInt), + type: nonNull(GraphQLInt), resolve: function(env) { - return graphQlUtils.toInt(env.source.startCursor); + return toInt(env.source.startCursor); } }, endCursor: { - type: graphQl.nonNull(graphQl.GraphQLInt), + type: nonNull(GraphQLInt), resolve: function(env) { - return graphQlUtils.toInt(env.source.endCursor); + return toInt(env.source.endCursor); } }, hasNext: { - type: graphQl.nonNull(graphQl.GraphQLBoolean) + type: nonNull(GraphQLBoolean) } } }); @@ -29,30 +36,30 @@ function createEdgeType(name, type) { name: name + 'Edge', fields: { node: { - type: graphQl.nonNull(type) + type: nonNull(type) }, cursor: { - type: graphQl.nonNull(graphQl.GraphQLInt), + type: nonNull(GraphQLInt), resolve: function(env) { - return graphQlUtils.toInt(env.source.cursor); + return toInt(env.source.cursor); } } } }); } -exports.createConnectionType = function(name, type) { +export function createConnectionType(name, type) { return schemaGenerator.createObjectType({ name: name + 'Connection', fields: { totalCount: { - type: graphQl.nonNull(graphQl.GraphQLInt), + type: nonNull(GraphQLInt), resolve: function(env) { return env.source.total; } }, edges: { - type: graphQl.list(createEdgeType(name, type)), + type: list(createEdgeType(name, type)), resolve: function(env) { var hits = env.source.hits; var edges = []; @@ -65,7 +72,7 @@ exports.createConnectionType = function(name, type) { return edges; } }, - aggregations: createAggregationsFiled(), + aggregations: createAggregationsField(), pageInfo: { type: pageInfoType, resolve: function(env) { @@ -82,4 +89,4 @@ exports.createConnectionType = function(name, type) { } } }); -}; +} diff --git a/src/main/resources/services/graphql/types/objects/idProvider.js b/src/main/resources/services/graphql/types/objects/idProvider.ts similarity index 59% rename from src/main/resources/services/graphql/types/objects/idProvider.js rename to src/main/resources/services/graphql/types/objects/idProvider.ts index 4303b353b..2056b2f9b 100644 --- a/src/main/resources/services/graphql/types/objects/idProvider.js +++ b/src/main/resources/services/graphql/types/objects/idProvider.ts @@ -1,35 +1,44 @@ -var graphQl = require('/lib/graphql'); +import { + GraphQLBoolean, + GraphQLString, + list, + reference + // @ts-expect-error Cannot find module '/lib/graphql' or its corresponding type declarations.ts(2307) +} from '/lib/graphql'; +import { + IdProviderAccessEnum, + IdProviderModeEnum +} from '../enums'; +import { UserItemType } from './userItem'; +import { + getIdProviderMode, + getPermissions +} from '/lib/idproviders'; +import { schemaGenerator } from '../../schemaUtil'; -var graphQlEnums = require('../enums'); - -var graphQlUserItem = require('./userItem'); - -var idprovidersLib = require('/lib/idproviders'); - -var schemaGenerator = require('../../schemaUtil').schemaGenerator; var IdProviderAccessControlEntryType = schemaGenerator.createObjectType({ name: 'IdProviderAccessControlEntry', description: 'Domain representation of id provider access control entry', fields: { principal: { - type: graphQl.reference('Principal') + type: reference('Principal') }, access: { - type: graphQlEnums.IdProviderAccessEnum + type: IdProviderAccessEnum } } }); -exports.IdProviderConfig = schemaGenerator.createObjectType({ +export const IdProviderConfig = schemaGenerator.createObjectType({ name: 'IdProviderConfig', description: 'Domain representation of auth config for id provider', fields: { applicationKey: { - type: graphQl.GraphQLString + type: GraphQLString }, config: { - type: graphQl.GraphQLString, + type: GraphQLString, resolve: function(env) { return JSON.stringify(env.source.config); // TODO Create object type for property array @@ -38,80 +47,83 @@ exports.IdProviderConfig = schemaGenerator.createObjectType({ } }); -exports.IdProviderType = schemaGenerator.createObjectType({ +export const IdProviderType = schemaGenerator.createObjectType({ name: 'IdProvider', description: 'Domain representation of an id provider', - interfaces: [graphQlUserItem.UserItemType], + interfaces: [UserItemType], fields: { key: { - type: graphQl.GraphQLString, + type: GraphQLString, resolve: function(env) { return env.source.key || env.source._name; } }, name: { - type: graphQl.GraphQLString, + type: GraphQLString, resolve: function(env) { return env.source.key || env.source._name; } }, path: { - type: graphQl.GraphQLString, + type: GraphQLString, resolve: function(env) { return '/identity/' + (env.source.key || env.source._name); } }, displayName: { - type: graphQl.GraphQLString + type: GraphQLString }, description: { - type: graphQl.GraphQLString + type: GraphQLString }, idProviderConfig: { - type: exports.IdProviderConfig + type: IdProviderConfig }, idProviderMode: { - type: graphQlEnums.IdProviderModeEnum, + type: IdProviderModeEnum, resolve: function(env) { var idProviderKey = env.source.idProviderConfig && env.source.idProviderConfig.applicationKey; return idProviderKey - ? idprovidersLib.getIdProviderMode(idProviderKey) + ? getIdProviderMode(idProviderKey) : null; } }, permissions: { - type: graphQl.list(IdProviderAccessControlEntryType), + type: list(IdProviderAccessControlEntryType), resolve: function(env) { - return idprovidersLib.getPermissions(env.source.key); + return getPermissions(env.source.key); } }, modifiedTime: { - type: graphQl.GraphQLString, + type: GraphQLString, resolve: function(env) { return env.source._timestamp; } } } }); + +// This seems like very bad code, trying to overwrite the state inside another module? +// Perhaps this worked when things are bundled into one file? graphQlUserItem.typeResolverMap.idProviderType = exports.IdProviderType; -exports.IdProviderDeleteType = schemaGenerator.createObjectType({ +export const IdProviderDeleteType = schemaGenerator.createObjectType({ name: 'IdProviderDelete', description: 'Result of an idProvider delete operation', fields: { key: { - type: graphQl.GraphQLString, + type: GraphQLString, resolve: function (env) { return env.source.idProviderKey; } }, deleted: { - type: graphQl.GraphQLBoolean + type: GraphQLBoolean }, reason: { - type: graphQl.GraphQLString + type: GraphQLString } } }); diff --git a/src/main/resources/services/graphql/types/objects/index.js b/src/main/resources/services/graphql/types/objects/index.ts similarity index 97% rename from src/main/resources/services/graphql/types/objects/index.js rename to src/main/resources/services/graphql/types/objects/index.ts index fe6797c63..d887d0f2d 100644 --- a/src/main/resources/services/graphql/types/objects/index.js +++ b/src/main/resources/services/graphql/types/objects/index.ts @@ -6,7 +6,7 @@ var graphQlUserItem = require('./userItem'); var graphQlTypes = require('./types'); var graphQlRepository = require('./repository'); -module.exports = { +export = { IdProviderType: graphQlIdProvider.IdProviderType, IdProviderDeleteType: graphQlIdProvider.IdProviderDeleteType, PrincipalType: graphQlPrincipal.PrincipalType, diff --git a/src/main/resources/services/graphql/types/objects/principal.js b/src/main/resources/services/graphql/types/objects/principal.ts similarity index 100% rename from src/main/resources/services/graphql/types/objects/principal.js rename to src/main/resources/services/graphql/types/objects/principal.ts diff --git a/src/main/resources/services/graphql/types/objects/repository.js b/src/main/resources/services/graphql/types/objects/repository.ts similarity index 100% rename from src/main/resources/services/graphql/types/objects/repository.js rename to src/main/resources/services/graphql/types/objects/repository.ts diff --git a/src/main/resources/services/graphql/types/objects/types.js b/src/main/resources/services/graphql/types/objects/types.ts similarity index 60% rename from src/main/resources/services/graphql/types/objects/types.js rename to src/main/resources/services/graphql/types/objects/types.ts index 42b142a75..de2e1d79b 100644 --- a/src/main/resources/services/graphql/types/objects/types.js +++ b/src/main/resources/services/graphql/types/objects/types.ts @@ -1,20 +1,24 @@ -var graphQl = require('/lib/graphql'); +import { + GraphQLInt, + list, + nonNull + // @ts-expect-error Cannot find module '/lib/graphql' or its corresponding type declarations.ts(2307) +} from '/lib/graphql'; +import { AggregationType } from './aggregations'; +import { schemaGenerator } from '../../schemaUtil'; -var graphQlAggregations = require('./aggregations'); -var schemaGenerator = require('../../schemaUtil').schemaGenerator; - -exports.TypesType = schemaGenerator.createObjectType({ +export = schemaGenerator.createObjectType({ name: 'Types', fields: { totalCount: { - type: graphQl.nonNull(graphQl.GraphQLInt), + type: nonNull(GraphQLInt), resolve: function(env) { return env.source.total; } }, aggregations: { - type: graphQl.list(graphQlAggregations.AggregationType), + type: list(AggregationType), resolve: function(env) { var aggregations = env.source.aggregations; var aggs = []; diff --git a/src/main/resources/services/graphql/types/objects/userItem.js b/src/main/resources/services/graphql/types/objects/userItem.js deleted file mode 100644 index 11ec725c2..000000000 --- a/src/main/resources/services/graphql/types/objects/userItem.js +++ /dev/null @@ -1,38 +0,0 @@ -var graphQl = require('/lib/graphql'); - -var schemaGenerator = require('../../schemaUtil').schemaGenerator; - -exports.typeResolverMap = { - principalType: null, - idProviderType: null -}; - -exports.UserItemType = schemaGenerator.createInterfaceType({ - name: 'UserItem', - description: 'User item is a base entity for every principal or id provider', - typeResolver: function(source) { - return source.principalType - ? exports.typeResolverMap.principalType - : exports.typeResolverMap.idProviderType; - }, - fields: { - key: { - type: graphQl.GraphQLString - }, - name: { - type: graphQl.GraphQLString - }, - path: { - type: graphQl.GraphQLString - }, - displayName: { - type: graphQl.GraphQLString - }, - description: { - type: graphQl.GraphQLString - }, - modifiedTime: { - type: graphQl.GraphQLString - } - } -}); diff --git a/src/main/resources/services/graphql/types/objects/userItem.ts b/src/main/resources/services/graphql/types/objects/userItem.ts new file mode 100644 index 000000000..64efc5682 --- /dev/null +++ b/src/main/resources/services/graphql/types/objects/userItem.ts @@ -0,0 +1,38 @@ +// @ts-expect-error Cannot find module '/lib/graphql' or its corresponding type declarations.ts(2307) +import { GraphQLString } from '/lib/graphql'; +import { schemaGenerator } from '../../schemaUtil'; + +export const typeResolverMap = { + principalType: null, + idProviderType: null +}; + +export const UserItemType = schemaGenerator.createInterfaceType({ + name: 'UserItem', + description: 'User item is a base entity for every principal or id provider', + typeResolver: function(source) { + return source.principalType + ? typeResolverMap.principalType + : typeResolverMap.idProviderType; + }, + fields: { + key: { + type: GraphQLString + }, + name: { + type: GraphQLString + }, + path: { + type: GraphQLString + }, + displayName: { + type: GraphQLString + }, + description: { + type: GraphQLString + }, + modifiedTime: { + type: GraphQLString + } + } +}); diff --git a/src/main/resources/services/graphql/utils.js b/src/main/resources/services/graphql/utils.ts similarity index 69% rename from src/main/resources/services/graphql/utils.js rename to src/main/resources/services/graphql/utils.ts index 3ed71b380..a24d66177 100644 --- a/src/main/resources/services/graphql/utils.js +++ b/src/main/resources/services/graphql/utils.ts @@ -1,4 +1,4 @@ -exports.toArray = function(object) { +export function toArray(object) { if (!object) { return []; } @@ -6,8 +6,8 @@ exports.toArray = function(object) { return object; } return [object]; -}; +} -exports.toInt = function(number, defaultValue) { +export function toInt(number, defaultValue) { return number == null ? defaultValue.intValue() : number.intValue(); -}; +} diff --git a/src/main/resources/services/i18n/i18n.js b/src/main/resources/services/i18n/i18n.js deleted file mode 100644 index 05662a87b..000000000 --- a/src/main/resources/services/i18n/i18n.js +++ /dev/null @@ -1,21 +0,0 @@ -var i18n = require('/lib/xp/i18n'); -var admin = require('/lib/xp/admin'); - -exports.get = function () { - - return { - status: 200, - contentType: 'application/json', - body: getPhrases() - } -}; - -var getPhrases = function() { - var locales = admin.getLocales(); - var bundle = i18n.getPhrases(locales, ['i18n/common']); - var phrases = i18n.getPhrases(locales, ['i18n/phrases']); - - for (var key in phrases) { bundle[key] = phrases[key] } - - return bundle; -}; diff --git a/src/main/resources/services/i18n/i18n.ts b/src/main/resources/services/i18n/i18n.ts new file mode 100644 index 000000000..b2e08bddb --- /dev/null +++ b/src/main/resources/services/i18n/i18n.ts @@ -0,0 +1,14 @@ +import { getLocales } from '/lib/xp/admin'; +import { getPhrases } from '/lib/xp/i18n'; + +export function get() { + const locales = getLocales(); + const body = getPhrases(locales, ['i18n/common']); + const phrases = getPhrases(locales, ['i18n/phrases']); + for (var key in phrases) { body[key] = phrases[key] } + return { + status: 200, + contentType: 'application/json', + body + } +} diff --git a/src/main/resources/static/app/inputtype/authapplicationselector/AuthApplicationSelector.ts b/src/main/resources/static/app/inputtype/authapplicationselector/AuthApplicationSelector.ts index 9ed98c616..37ec1b8f4 100644 --- a/src/main/resources/static/app/inputtype/authapplicationselector/AuthApplicationSelector.ts +++ b/src/main/resources/static/app/inputtype/authapplicationselector/AuthApplicationSelector.ts @@ -15,9 +15,6 @@ import {FormContext} from '@enonic/lib-admin-ui/form/FormContext'; import {AuthApplicationSelectedOptionView} from './AuthApplicationSelectedOptionView'; import {AuthApplicationComboBox} from './AuthApplicationComboBox'; import {BaseInputTypeManagingAdd} from '@enonic/lib-admin-ui/form/inputtype/support/BaseInputTypeManagingAdd'; -import {InputValidationRecording} from '@enonic/lib-admin-ui/form/inputtype/InputValidationRecording'; -import {Class} from '@enonic/lib-admin-ui/Class'; -import {InputTypeManager} from '@enonic/lib-admin-ui/form/inputtype/InputTypeManager'; import {Input} from '@enonic/lib-admin-ui/form/Input'; import {AuthApplicationSelectedOptionsView} from './AuthApplicationSelectedOptionsView'; @@ -202,5 +199,3 @@ export class AuthApplicationSelector return this.comboBox.giveFocus(); } } - -InputTypeManager.register(new Class('AuthApplicationSelector', AuthApplicationSelector)); diff --git a/src/main/resources/static/app/inputtype/index.ts b/src/main/resources/static/app/inputtype/index.ts new file mode 100644 index 000000000..ac733d602 --- /dev/null +++ b/src/main/resources/static/app/inputtype/index.ts @@ -0,0 +1,2 @@ +export { AuthApplicationSelector } from './authapplicationselector/AuthApplicationSelector'; +export { PrincipalSelector } from './selector/PrincipalSelector'; diff --git a/src/main/resources/static/main.ts b/src/main/resources/static/main.ts index a8a18fe68..23797d902 100644 --- a/src/main/resources/static/main.ts +++ b/src/main/resources/static/main.ts @@ -14,17 +14,16 @@ import {TabbedAppBar} from '@enonic/lib-admin-ui/app/bar/TabbedAppBar'; import {AppHelper} from '@enonic/lib-admin-ui/util/AppHelper'; import {i18nInit} from '@enonic/lib-admin-ui/util/MessagesInitializer'; import {CONFIG} from '@enonic/lib-admin-ui/util/Config'; -import {PrincipalSelector} from './app/inputtype/selector/PrincipalSelector'; import {InputTypeManager} from '@enonic/lib-admin-ui/form/inputtype/InputTypeManager'; import {Class} from '@enonic/lib-admin-ui/Class'; +import { + AuthApplicationSelector, + PrincipalSelector +} from './app/inputtype/'; const body = Body.get(); -// Dynamically import and execute all input types, since they are used -// on-demand, when parsing XML schemas and has not real usage in app -declare let require: { context: (directory: string, useSubdirectories: boolean, filter: RegExp) => void }; -const importAll = r => r.keys().forEach(r); -importAll(require.context('./app/inputtype', true, /^(?!\.[\/\\]ui).*/)); +InputTypeManager.register(new Class('AuthApplicationSelector', AuthApplicationSelector)); function getApplication(): Application { const assetsUri: string = CONFIG.getString('assetsUri');