Imported Upstream version 4.6.2

This commit is contained in:
Mario Fetka
2021-07-25 07:32:41 +02:00
commit 8ff3be4216
1788 changed files with 1900965 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
AUTOMAKE_OPTIONS = 1.7
NULL =
SUBDIRS = \
libs \
$(NULL)
EXTRA_DIST = \
build.profile.js \
dojo.profile.js \
freeipa \
webui.profile.js

739
install/ui/src/Makefile.in Normal file
View File

@@ -0,0 +1,739 @@
# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = install/ui/src
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/VERSION.m4 \
$(top_srcdir)/server.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
install-exec-recursive install-html-recursive \
install-info-recursive install-pdf-recursive \
install-ps-recursive install-recursive installcheck-recursive \
installdirs-recursive pdf-recursive ps-recursive \
tags-recursive uninstall-recursive
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
$(RECURSIVE_TARGETS) \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
distdir
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
API_VERSION = @API_VERSION@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
CMOCKA_LIBS = @CMOCKA_LIBS@
CONFIG_STATUS = @CONFIG_STATUS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CRYPTO_CFLAGS = @CRYPTO_CFLAGS@
CRYPTO_LIBS = @CRYPTO_LIBS@
CYGPATH_W = @CYGPATH_W@
DATA_VERSION = @DATA_VERSION@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DIRSRV_CFLAGS = @DIRSRV_CFLAGS@
DIRSRV_LIBS = @DIRSRV_LIBS@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GETTEXT_DOMAIN = @GETTEXT_DOMAIN@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GIT_BRANCH = @GIT_BRANCH@
GIT_VERSION = @GIT_VERSION@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GREP = @GREP@
INI_CFLAGS = @INI_CFLAGS@
INI_LIBS = @INI_LIBS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
IPAPLATFORM = @IPAPLATFORM@
IPA_DATA_DIR = @IPA_DATA_DIR@
IPA_SYSCONF_DIR = @IPA_SYSCONF_DIR@
JSLINT = @JSLINT@
KRAD_LIBS = @KRAD_LIBS@
KRB5KDC_SERVICE = @KRB5KDC_SERVICE@
KRB5_CFLAGS = @KRB5_CFLAGS@
KRB5_LIBS = @KRB5_LIBS@
LD = @LD@
LDAP_CFLAGS = @LDAP_CFLAGS@
LDAP_LIBS = @LDAP_LIBS@
LDFLAGS = @LDFLAGS@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBINTL_LIBS = @LIBINTL_LIBS@
LIBOBJS = @LIBOBJS@
LIBPDB_NAME = @LIBPDB_NAME@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIBVERTO_CFLAGS = @LIBVERTO_CFLAGS@
LIBVERTO_LIBS = @LIBVERTO_LIBS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
MK_ASSIGN = @MK_ASSIGN@
MK_ELSE = @MK_ELSE@
MK_ENDIF = @MK_ENDIF@
MK_IFEQ = @MK_IFEQ@
MSGATTRIB = @MSGATTRIB@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
NAMED_GROUP = @NAMED_GROUP@
NDRNBT_CFLAGS = @NDRNBT_CFLAGS@
NDRNBT_LIBS = @NDRNBT_LIBS@
NDRPAC_CFLAGS = @NDRPAC_CFLAGS@
NDRPAC_LIBS = @NDRPAC_LIBS@
NDR_CFLAGS = @NDR_CFLAGS@
NDR_LIBS = @NDR_LIBS@
NM = @NM@
NMEDIT = @NMEDIT@
NSPR_CFLAGS = @NSPR_CFLAGS@
NSPR_LIBS = @NSPR_LIBS@
NSS_CFLAGS = @NSS_CFLAGS@
NSS_LIBS = @NSS_LIBS@
NUM_VERSION = @NUM_VERSION@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
ODS_USER = @ODS_USER@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
POPT_CFLAGS = @POPT_CFLAGS@
POPT_LIBS = @POPT_LIBS@
POSUB = @POSUB@
PYLINT = @PYLINT@
PYTHON = @PYTHON@
PYTHON2 = @PYTHON2@
PYTHON3 = @PYTHON3@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_INSTALL_EXTRA_OPTIONS = @PYTHON_INSTALL_EXTRA_OPTIONS@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
SAMBA40EXTRA_LIBPATH = @SAMBA40EXTRA_LIBPATH@
SAMBAUTIL_CFLAGS = @SAMBAUTIL_CFLAGS@
SAMBAUTIL_LIBS = @SAMBAUTIL_LIBS@
SASL_CFLAGS = @SASL_CFLAGS@
SASL_LIBS = @SASL_LIBS@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SSSCERTMAP_CFLAGS = @SSSCERTMAP_CFLAGS@
SSSCERTMAP_LIBS = @SSSCERTMAP_LIBS@
SSSIDMAP_CFLAGS = @SSSIDMAP_CFLAGS@
SSSIDMAP_LIBS = @SSSIDMAP_LIBS@
SSSNSSIDMAP_CFLAGS = @SSSNSSIDMAP_CFLAGS@
SSSNSSIDMAP_LIBS = @SSSNSSIDMAP_LIBS@
STRIP = @STRIP@
TALLOC_CFLAGS = @TALLOC_CFLAGS@
TALLOC_LIBS = @TALLOC_LIBS@
TEVENT_CFLAGS = @TEVENT_CFLAGS@
TEVENT_LIBS = @TEVENT_LIBS@
UNISTRING_LIBS = @UNISTRING_LIBS@
UNLINK = @UNLINK@
USE_NLS = @USE_NLS@
UUID_CFLAGS = @UUID_CFLAGS@
UUID_LIBS = @UUID_LIBS@
VENDOR_SUFFIX = @VENDOR_SUFFIX@
VERSION = @VERSION@
XGETTEXT = @XGETTEXT@
XGETTEXT_015 = @XGETTEXT_015@
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
XMLRPC_LIBS = @XMLRPC_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
i18ntests = @i18ntests@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
krb5rundir = @krb5rundir@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
sysconfenvdir = @sysconfenvdir@
systemdsystemunitdir = @systemdsystemunitdir@
systemdtmpfilesdir = @systemdtmpfilesdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = 1.7
NULL =
SUBDIRS = \
libs \
$(NULL)
EXTRA_DIST = \
build.profile.js \
dojo.profile.js \
freeipa \
webui.profile.js
all: all-recursive
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign install/ui/src/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign install/ui/src/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
# (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
@fail=; \
if $(am__make_keepgoing); then \
failcom='fail=yes'; \
else \
failcom='exit 1'; \
fi; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-recursive
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-recursive
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-recursive
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
$(am__make_dryrun) \
|| test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-recursive
all-am: Makefile
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-recursive
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am:
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-man:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am:
.MAKE: $(am__recursive_targets) install-am install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
check-am clean clean-generic clean-libtool cscopelist-am ctags \
ctags-am distclean distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
installdirs-am maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
ps ps-am tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@@ -0,0 +1,108 @@
//
// BUILDER profile
//
var profile = (function(){
return {
basePath: ".",
releaseDir: "../release",
releaseName: "build",
action: "release",
layerOptimize: false,
optimize: false,
cssOptimize: false,
mini: true,
stripConsole: "warn",
selectorEngine: "lite",
staticHasFeatures: {
"host-rhino":1,
"host-browser":0,
"host-node":0,
"dom":0,
"dojo-has-api":1,
"dojo-xhr-factory":0,
"dojo-inject-api":1,
"dojo-timeout-api":0,
"dojo-trace-api":1,
"dojo-loader-catches":0,
"dojo-dom-ready-api":0,
"dojo-dom-ready-plugin":0,
"dojo-ready-api":1,
"dojo-error-api":1,
"dojo-publish-privates":1,
"dojo-gettext-api":1,
"dojo-sniff":0,
"dojo-loader":1,
"dojo-test-xd":0,
"dojo-test-sniff":0
},
packages:[{
name: "dojo",
location: "dojo"
},{
name: "build",
location: "build"
}],
layers: {
"build/build": {
include: [
'dojo/dojo',
'build/buildControlBase',
'build/argv',
'build/build.profile',
'build/discover',
'build/messages',
'build/removeComments',
'build/fs',
'build/main',
'build/fileUtils',
'build/process',
'build/v1xProfiles',
'build/replace',
'build/fileHandleThrottle',
'build/buildControl',
'build/commandLineArgs',
'build/stringify',
'build/buildControlDefault',
'build/version',
'build/plugins/querySelector',
'build/plugins/domReady',
'build/plugins/has',
'build/plugins/text',
'build/plugins/loadInit',
'build/plugins/require',
'build/plugins/i18n',
'build/transforms/depsDump',
'build/transforms/copy',
'build/transforms/trace',
'build/transforms/read',
'build/transforms/writeAmd',
'build/transforms/dojoPragmas',
'build/transforms/report',
'build/transforms/hasFindAll',
'build/transforms/hasFixup',
'build/transforms/writeDojo',
'build/transforms/depsScan',
'build/transforms/write',
'build/transforms/dojoReport',
'build/transforms/writeOptimized',
'build/transforms/insertSymbols',
'build/transforms/hasReport',
'build/transforms/writeCss',
'build/transforms/depsDeclarative',
'build/transforms/optimizeCss',
'build/node/fs',
'build/node/process',
'build/rhino/fs',
'build/rhino/process'
],
customBase: true,
boot: true
}
}
};
})();

View File

@@ -0,0 +1,102 @@
//
// DOJO profile
//
var profile = (function(){
return {
basePath: ".",
releaseDir: "../release",
releaseName: "dojo",
action: "release",
layerOptimize: false,
optimize: false,
cssOptimize: false,
mini: true,
stripConsole: "warn",
selectorEngine: "lite",
defaultConfig: {
hasCache:{
"config-deferredInstrumentation": 0,
"config-dojo-loader-catches": 0,
"config-tlmSiblingOfDojo": 0,
"dojo-amd-factory-scan": 0,
"dojo-combo-api": 0,
"dojo-config-api": 1,
"dojo-config-require": 0,
"dojo-debug-messages": 0,
"dojo-dom-ready-api": 1,
"dojo-firebug": 0,
"dojo-guarantee-console": 1,
"dojo-has-api": 1,
"dojo-inject-api": 1,
"dojo-loader": 1,
"dojo-log-api": 0,
"dojo-modulePaths": 0,
"dojo-moduleUrl": 0,
"dojo-publish-privates": 0,
"dojo-requirejs-api": 0,
"dojo-sniff": 0,
"dojo-sync-loader": 0,
"dojo-test-sniff": 0,
"dojo-timeout-api": 0,
"dojo-trace-api": 0,
"dojo-undef-api": 0,
"dojo-v1x-i18n-Api": 1,
"dom": 1,
"host-browser": 1,
"extend-dojo": 1
},
async: 1
},
packages:[
{
name: "dojo",
location: "dojo"
}
],
layers: {
"dojo/dojo": {
// explicitly include all modules which we want in our build
include: [
"dojo/dojo",
"dojo/domReady",
"dojo/_base/declare",
// ^ core is about 20KB
"dojo/_base/lang",
"dojo/_base/array",
"dojo/string",
// ^ adds 10KB
"dojo/dom",
"dojo/dom-construct",
"dojo/dom-class",
"dojo/dom-style",
"dojo/dom-prop",
// ^ adds 20KB, with router only 5KB
"dojo/Stateful",
"dojo/Evented",
"dojo/on",
"dojo/io-query",
//
"dojo/keys",
"dojo/router",
"dojo/hash", //used by router
"dojo/topic", //used by router
// ^ adds 20 KB, most of it is dojo/dom*
"dojo/store/Observable",
"dojo/store/Memory",
"dojo/query",
"dojo/NodeList-dom",
"dojo/promise/all"
// Total size: 75KB
],
customBase: true,
boot: true
}
}
};
})();

View File

@@ -0,0 +1,613 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/declare',
'dojo/_base/array',
'dojo/Deferred',
'dojo/on',
'dojo/topic',
'dojo/query',
'dojo/dom-class',
'./auth',
'./json2',
'./widgets/App',
'./widgets/FacetContainer',
'./ipa',
'./rpc',
'./reg',
'./config',
'./widget',
'./navigation/Menu',
'./navigation/Router',
'./navigation/routing',
'./navigation/menu_spec',
'./plugins/load_page'
],
function(declare, array, Deferred, on, topic, query, dom_class, auth,
JSON, App_widget, FacetContainer, IPA, rpc, reg, config, widget_mod,
Menu, Router, routing, menu_spec) {
/**
* Application controller
*
* Controls interaction between navigation, menu and facets.
*
* @class Application_controller
*/
var App = declare(null, {
/**
* Facet container map
*/
containers: null,
app_widget: null,
router: null,
menu: null,
initialized: false,
facet_changing: false,
/**
* Listeners for user menu items
*/
on_profile_listener: null,
on_passwd_reset_listener: null,
on_logout_listener: null,
on_item_select_listener: null,
on_configuration_listerer: null,
on_about_listener: null,
/**
* Currently displayed facet
*
*/
current_facet: null,
/**
* Currently displayed facet container
*/
current_container: null,
init: function() {
this.menu = new Menu();
this.router = new Router();
routing.init(this.router);
var body_node = query('body')[0];
this.app_widget = new App_widget();
this.app_widget.container_node = body_node;
this.app_widget.menu_widget.set_menu(this.menu);
var simple_container = new FacetContainer();
simple_container.container_node = body_node;
var notification_container = new FacetContainer({
container_node: body_node,
id: "notification",
'class': ''
});
this.containers = {
// Default view
main: {
widget: this.app_widget
},
// Mainly for standalone facets
simple: {
widget: simple_container
}
};
this.register_user_menu_listeners();
on(this.router, 'facet-show', this.on_facet_show.bind(this));
on(this.router, 'facet-change', this.on_facet_change.bind(this));
on(this.router, 'facet-change-canceled', this.on_facet_canceled.bind(this));
on(this.router, 'error', this.on_router_error.bind(this));
topic.subscribe('phase-error', this.on_phase_error.bind(this));
topic.subscribe('authenticate', this.on_authenticate.bind(this));
this.app_widget.render();
this.app_widget.hide();
simple_container.render();
simple_container.hide();
notification_container.render();
var load_facet = reg.facet.get('load');
this.show_facet(load_facet);
IPA.opened_dialogs.start_handling(this);
},
register_user_menu_listeners: function() {
this.on_profile_listener = on(this.app_widget, 'profile-click',
this.on_profile.bind(this));
this.on_passwd_reset_listener = on(this.app_widget,
'password-reset-click', this.on_password_reset.bind(this));
this.on_logout_listener = on(this.app_widget, 'logout-click',
this.on_logout.bind(this));
this.on_item_select_listener = on(this.app_widget.menu_widget,
'item-select', this.on_menu_click.bind(this));
this.on_configuration_listerer = on(this.app_widget,
'configuration-click', this.on_configuration.bind(this));
this.on_about_listener = on(this.app_widget,
'about-click', this.on_about.bind(this));
},
/**
* Turns off one item in user dropdown menu and remove its listener.
* @param {string} name of the user menu item which should be disabled
* @param {Object} listener disable di
*/
disable_user_menu_item: function(name, listener) {
this.app_widget.disable_user_menu_item(name);
listener.remove();
},
/**
* Gets:
* * metadata
* * server configuration
* * user information
*/
get_configuration: function(success_handler, error_handler) {
IPA.init({ on_success: success_handler, on_error: error_handler});
},
/**
* Deduces current application profile - administraion or self-service.
* Initializes profiles's menu.
*/
choose_profile: function() {
this.update_logged_in(true);
var selfservice = this.is_selfservice();
this.app_widget.menu_widget.ignore_changes = true;
if (selfservice) {
if (this.is_aduser_selfservice()) {
this.menu.name = menu_spec.ad_self_service.name;
this.menu.add_items(menu_spec.ad_self_service.items);
this.disable_user_menu_item('password_reset',
this.on_passwd_reset_listener);
} else {
this.menu.name = menu_spec.self_service.name;
this.menu.add_items(menu_spec.self_service.items);
}
} else {
this.menu.name = menu_spec.admin.name;
this.menu.add_items(menu_spec.admin.items);
}
this.app_widget.menu_widget.ignore_changes = false;
this.app_widget.menu_widget.render();
this.app_widget.menu_widget.select(this.menu.selected);
},
start_runtime: function() {
this.run_time = new Deferred();
// hide load or login facets
this.hide_facet();
IPA.update_password_expiration();
// now we are ready for displaying a facet,
// it can match a facet if hash is set
this.router.startup();
// choose default facet if not defined by route
if (!this.current_facet) {
this.navigate_to_default();
}
return this.run_time.promise;
},
navigate_to_default: function() {
if (IPA.is_selfservice) {
this.on_profile();
} else {
routing.navigate(routing.default_path);
}
},
start_logout: function() {
IPA.logout();
},
is_selfservice: function() {
var whoami = IPA.whoami.data;
var self_service = true;
if (whoami.hasOwnProperty('memberof_group') &&
whoami.memberof_group.indexOf('admins') !== -1) {
self_service = false;
} else if (whoami.hasOwnProperty('memberofindirect_group')&&
whoami.memberofindirect_group.indexOf('admins') !== -1) {
self_service = false;
} else if (whoami.hasOwnProperty('memberof_role') &&
whoami.memberof_role.length > 0) {
self_service = false;
} else if (whoami.hasOwnProperty('memberofindirect_role') &&
whoami.memberofindirect_role.length > 0) {
self_service = false;
}
IPA.is_selfservice = self_service; // quite ugly, needed for users
return self_service;
},
is_aduser_selfservice: function() {
var selfservice = IPA.whoami.metadata.object === 'idoverrideuser';
// quite ugly, needed for users and iduseroverride to hide breadcrumb
IPA.is_aduser_selfservice = selfservice;
return selfservice;
},
update_logged_in: function(logged_in) {
this.app_widget.set('logged', logged_in);
var whoami = IPA.whoami;
var fullname = '';
var entity = whoami.metadata.object;
if (whoami.data.cn) {
fullname = whoami.data.cn[0];
} else if (whoami.data.displayname) {
fullname = whoami.data.displayname[0];
} else if (whoami.data.gecos) {
fullname = whoami.data.gecos[0];
} else if (whoami.data.krbprincipalname) {
fullname = whoami.data.krbprincipalname[0];
} else if (whoami.data.ipaoriginaluid) {
fullname = whoami.data.ipaoriginaluid[0];
}
this.app_widget.set('fullname', fullname);
},
on_profile: function() {
routing.navigate(['entity', IPA.whoami.metadata.object, 'details',
IPA.whoami.metadata.arguments]);
},
on_logout: function(event) {
this.run_time.resolve();
},
on_password_reset: function() {
IPA.password_selfservice();
},
on_configuration: function() {
var dialog = IPA.dialog({
title: '@i18n:customization.customization',
fields: [
{
$type: 'text',
name: 'pagination_size',
label: '@i18n:customization.table_pagination',
validators: ['positive_integer']
}
]
});
dialog.create_button({
name: 'save',
label: '@i18n:buttons.save',
click: function () {
if (!dialog.validate()) {
widget_mod.focus_invalid(dialog);
return;
}
var widget = dialog.get_field('pagination_size').widget;
var new_value = widget.get_value()[0];
config.set('table_page_size', new_value, true);
topic.publish('change-pagination');
dialog.close();
}
});
dialog.create_button({
name: 'cancel',
label: '@i18n:buttons.cancel',
click: function () {
dialog.close();
}
});
dialog.open();
var size = config.get('table_page_size').toString();
dialog.get_field('pagination_size').set_value([size]);
},
on_about: function() {
var dialog = IPA.about_dialog();
dialog.open();
},
on_phase_error: function(error) {
error = error || {};
var name = error.name || 'Runtime error';
var error_container = $('<div/>', {
'class': 'container facet-content facet-error'
}).appendTo($('.app-container .content').empty());
error_container.append($('<h1/>', { text: name }));
var details = $('<div/>', {
'class': 'error-details'
}).appendTo(error_container);
details.append($('<p/>', { text: 'Web UI got in unrecoverable state during "' + error.phase + '" phase.' }));
if (error.name) window.console.error(error.name);
if (error.results) {
details.append('<h3>Technical details:</h3>');
var msg = error.results.message;
if (msg) {
window.console.error(msg);
details.append($('<div/>', { text: msg }));
}
if (error.results.stack) {
var stack = error.results.stack.toString();
window.console.error(stack);
details.append($('<div/>').append($('<code/>', { text: stack })));
}
}
},
on_facet_change: function(event) {
//this.facet_changing = true;
var new_facet = event.facet;
var current_facet = this.current_facet;
if (current_facet === new_facet) return;
if (current_facet && !current_facet.can_leave()) {
var permit_clb = function() {
// Some facet's might not call reset before this call but after
// so they are still dirty. Calling reset prevent's opening of
// dirty dialog again.
if (current_facet.is_dirty()) current_facet.reset(); //TODO change
this.router.navigate_to_hash(event.hash, event.facet);
}.bind(this);
var dialog = current_facet.show_leave_dialog(permit_clb);
this.router.canceled = true;
dialog.open();
}
},
on_facet_canceled: function(event) {
},
on_facet_state_changed: function(event) {
if (event.facet === this.current_facet) {
routing.update_hash(event.facet, event.state);
}
},
on_facet_show: function(event) {
this.show_facet(event.facet);
},
show_facet: function(facet) {
// prevent changing facet when authenticating
if (this.current_facet && this.current_facet.name === 'login' &&
!auth.current.authenticated && facet.requires_auth) {
return;
}
// choose container
var container = this.containers[facet.preferred_container];
if (!container) container = this.containers.main;
if (this.current_container !== container) {
if (this.current_container) {
this.current_container.widget.hide();
}
this.current_container = container;
this.current_container.widget.show();
}
// update menu
var menu_item = this._find_menu_item(facet);
if (menu_item) this.menu.select(menu_item);
// show facet
if (!facet.container_node) {
facet.container_node = container.widget.content_node;
on(facet, 'facet-state-change', this.on_facet_state_changed.bind(this));
}
if (this.current_facet !== facet) {
IPA.opened_dialogs.hide();
}
this.hide_facet();
this.current_facet = facet;
facet.show();
IPA.opened_dialogs.focus_top();
},
hide_facet: function() {
if (this.current_facet) {
this.current_facet.hide();
}
this.current_facet = null;
},
_find_menu_item: function(facet) {
var items = [];
// entity facets
if (facet.entity) {
items = this.menu.query({ entity: facet.entity.name, facet: facet.name });
}
// entity fallback
if (!items.total && facet.entity) {
items = this.menu.query({ entity: facet.entity.name });
}
// normal facets
if (!items.total) {
items = this.menu.query({ facet: facet.name });
}
// fallback: Top level item
if (!items.total) {
items = this.menu.query({ parent: null });
}
if (items.total) {
if (items.total === 1) return items[0];
// select the menu item with the most similar state as the facet
var best = items[0];
var best_score = 0;
var item, i, j, l, score;
var state = facet.state;
for (i=0, l=items.total; i<l; i++) {
item = items[i];
score = 0;
if (item.pkeys && facet.get_pkeys) {
var pkeys = facet.get_pkeys();
for (j=0, j=item.pkeys.length; j<l; j++) {
if (pkeys.indexOf(item.pkeys[j]) > -1) score++;
}
}
if (item.args) {
for (var name in item.args) {
if (!item.args.hasOwnProperty(name)) continue;
if (state[name] == item.args[name]) score++;
}
}
if (score > best_score) {
best_score = score;
best = item;
}
}
return best;
}
},
on_router_error: function(error) {
if (error.type === 'route') {
this.navigate_to_default();
}
},
/**
* Tries to find menu item with assigned facet and navigate to it.
*/
on_menu_click: function(menu_item) {
this._navigate_to_menu_item(menu_item);
},
_navigate_to_menu_item: function(menu_item) {
if (menu_item.entity) {
// entity pages
routing.navigate([
'entity',
menu_item.entity,
menu_item.facet,
menu_item.pkeys,
menu_item.args]);
} else if (menu_item.facet) {
// concrete facets
routing.navigate(['generic', menu_item.facet, menu_item.args]);
} else {
// categories, select first posible child, it may be the last
var children = this.menu.query({parent: menu_item.name });
if (children.total) {
var success = false;
for (var i=0; i<children.total;i++) {
success = this._navigate_to_menu_item(children[i]);
if (success) break;
}
} else {
return false;
}
}
return true;
},
/**
* Starts authentication process in authentication UI
* @returns {undefined}
*/
on_authenticate: function() {
var self = this;
if (this.auth_ui === 'dialog') {
var dummy_command = {
execute: function() {
topic.publish('auth-successful');
}
};
var dialog = IPA.unauthorized_dialog({
close_on_escape: false,
error_thrown: { name: '', message: ''},
command: dummy_command
});
dialog.open();
} else {
var facet = this.current_facet;
// we don't want the load facet to be displayed after successful auth
if (facet && facet.name === 'load') {
facet = null;
}
var login_facet = reg.facet.get('login');
on.once(login_facet, "logged_in", function() {
if (facet) {
self.show_facet(facet);
}
topic.publish('auth-successful');
});
this.show_facet(login_facet);
}
}
});
return App;
});

View File

@@ -0,0 +1,349 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/lang',
'dojo/on',
'./util'
],
function(declare, lang, on, util) {
/**
* Field binder
*
* Binds input widget with field - defines standard communication logic
* between widget and a field.
*
* Usage:
*
* var binder = new FieldBinder(widget, field).bind();
*
* // or
* var binder = new FieldBinder({
* field: field,
* widget: widget
* });
* binder.bind()
*
* @class FieldBinder
*/
var FieldBinder = declare([], {
/**
* Field
* @property {IPA.field}
*/
field: null,
/**
* Widget
* @property {IPA.input_widget}
*/
widget: null,
/**
* Binder is enabled
*
* Handlers are not be called when set to false.
*
* @property {boolean}
*/
enabled: true,
/**
* Handlers
* @protected
* @property {Function[]}
*/
handlers: null,
/**
* Value update is in progress
*
* When set, binder should not react to field's nor widget's value-change
* event.
*
* @property {boolean}
*/
updating: false,
/**
* Bind widget with field
*
* Listens for field's:
*
* - enable-change
* - valid-change
* - value-change
* - dirty-change
* - require-change
* - writable-change
* - readonly-change
* - reset
*
* Listens for widget's:
*
* - value-change
* - undo-click
*
* @param {boolean} hard
* Hard binding. Sets `field.widget` to `this.widget`.
* This option is for backward compatibility.
*/
bind: function(hard) {
var field = this.field;
var widget = this.widget;
if (hard) field.widget = widget;
this.handle(field, 'enable-change', this.on_field_enable_change);
this.handle(field, 'valid-change', this.on_field_valid_change);
this.handle(field, 'value-change', this.on_field_value_change);
this.handle(field, 'dirty-change', this.on_field_dirty_change);
this.handle(field, 'require-change', this.on_field_require_change);
this.handle(field, 'writable-change', this.on_field_writable_change);
this.handle(field, 'readonly-change', this.on_field_readonly_change);
this.handle(field, 'acl-rights-change', this.on_field_acl_rights_change);
this.handle(field, 'reset', this.on_field_reset);
this.handle(widget, 'value-change', this.on_widget_value_change);
this.handle(widget, 'undo-click', this.on_widget_undo_click);
return this;
},
/**
* Unbind all handlers
*/
unbind: function() {
var handler;
while ((handler = this.handlers.pop())) {
handler.remove();
}
},
/**
* Creates and registers the handler.
* Handler will be called in binder context and only if
* `this.enabled === true`.
*
* Do not use `on(target, type, handler)` directly.
*
* @param {Function} handler
* @return {Function} context bound handler
* @protected
*/
handle: function(target, type, handler) {
var _this = this;
var hndlr = function() {
if (_this.enabled !== true) return;
else {
handler.apply(_this, Array.prototype.slice.call(arguments, 0));
}
};
var reg_hndl = on(target, type, hndlr);
this.handlers.push(reg_hndl);
return hndlr;
},
/**
* Field enable change handler
*
* Reflect enabled state to widget
*
* @protected
*/
on_field_enable_change: function(event) {
this.widget.set_enabled(event.enabled);
},
/**
* Field valid change handler
* @protected
*/
on_field_valid_change: function(event) {
this.widget.set_valid(event.result);
},
/**
* Field dirty change handler
*
* Controls showing of widget's undo button
*
* @protected
*/
on_field_dirty_change: function(event) {
if (!this.field.undo) return;
if (event.dirty) {
this.widget.show_undo();
} else {
this.widget.hide_undo();
}
},
/**
* Field require change handler
*
* Updates widget's require state
*
* @protected
*/
on_field_require_change: function(event) {
this.widget.set_required(event.required);
},
/**
* Field require change handler
*
* Updates widget's require state
*
* @protected
*/
on_field_writable_change: function(event) {
this.widget.set_writable(event.writable);
},
/**
* Field require change handler
*
* Updates widget's require state
*
* @protected
*/
on_field_readonly_change: function(event) {
this.widget.set_read_only(event.read_only);
},
/**
* Field acl rights change handler
* @protected
*/
on_field_acl_rights_change: function(event) {
var readable= event.rights.indexOf('r') > -1;
if (this.widget.set_readable) {
this.widget.set_readable(readable);
}
},
/**
* Field reset handler
*
* @param {Object} event
* @protected
*/
on_field_reset: function(event) {
this.copy_properties();
},
/**
* Field value change handler
* @protected
*/
on_field_value_change: function(event) {
if (this.updating) return;
var format_result = util.format(this.field.ui_formatter, event.value);
if (format_result.ok) {
this.updating = true;
this.widget.update(format_result.value);
this.updating = false;
} else {
// this should not happen in ideal world
window.console.warn('field format error: '+this.field.name);
}
},
/**
* Widget value change handler
* @protected
*/
on_widget_value_change: function(event) {
if (this.updating) return;
var val = this.widget.save();
var format_result = util.parse(this.field.ui_parser, val);
if (format_result.ok) {
this.updating = true;
this.field.set_value(format_result.value);
this.updating = false;
} else {
this.field.set_valid(format_result);
}
},
/**
* Widget undo click handler
* @protected
*/
on_widget_undo_click: function(event) {
this.field.reset();
},
/**
* Copies `label`, `tooltip`, `measurement_unit`, `undo`, `writable`,
* `read_only` from field to widget
*/
copy_properties: function() {
var field = this.field;
var widget = this.widget;
if (field.label) widget.label = field.label;
if (field.tooltip) widget.tooltip = field.tooltip;
if (field.measurement_unit) widget.measurement_unit = field.measurement_unit;
widget.undo = field.undo;
widget.set_writable(field.writable);
widget.set_read_only(field.read_only);
widget.set_required(field.is_required());
return this;
},
constructor: function(arg1, arg2) {
this.handlers = [];
if (arg2) {
this.field = arg1;
this.widget = arg2;
} else {
arg1 = arg1 || {};
this.field = arg1.field;
this.widget = arg1.widget;
}
}
});
return FieldBinder;
});

View File

@@ -0,0 +1,203 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/on',
'./builder',
'./field',
'./ordered-map'
],
function(declare, on, builder, field_mod, ordered_map) {
/**
* Form mixin
*
* Manages fields and related logic.
*
* Expects that this mixin will be mixed in a class which will implement
* `Stateful`.
*
* @class FormMixin
*/
var FormMixin = declare([], {
/**
* Some field is dirty
* @property {boolean}
*/
dirty: null,
/**
* Fields
* @property {ordered_map}
*/
fields: null,
/**
* Builds fields on add if not already built
*
* @property {field.field_builder}
*/
field_builder: null,
/**
* Raised when `dirty` state changes
* @event dirty-change
*/
/**
* Raised after fields reset
* @event reset
*/
/**
* Get field by name
* @param {string} name
*/
get_field: function(name) {
return this.fields.get(name);
},
/**
* Get all fields
* @return {Array.<IPA.field>}
*/
get_fields: function() {
return this.fields.values;
},
/**
* Add field
* @param {IPA.field|Object|String} field
* Field or field spec
*/
add_field: function(field) {
field.container = this;
var built = this.field_builder.build_field(field);
this.register_field_listeners(built);
this.fields.put(field.name, built);
return built;
},
/**
* Add multiple fields
* @param {Array} fields
*/
add_fields: function(fields) {
if (!fields) return [];
var built = [];
for (var i=0; i<fields.length; i++) {
var f = this.add_field(fields[i]);
built.push(f);
}
return built;
},
/**
* Registers listeners for field events
* @param {IPA.field} field
* @protected
*/
register_field_listeners: function(field) {
on(field, 'dirty-change', this.on_field_dirty_change.bind(this));
},
/**
* Field's dirty-change handler
* @param {Object} event
* @protected
* @fires dirty-change
*/
on_field_dirty_change: function(event) {
var old = this.dirty;
if (event.dirty) {
this.dirty = true;
} else {
this.dirty = this.is_dirty();
}
if (old !== this.dirty) {
this.emit('dirty-change', { source: this, dirty: this.dirty });
}
},
/**
* Perform check if any field is dirty
*
* @return {boolean}
* - true: some field is dirty
* - false: all field's aren't dirty
*/
is_dirty: function() {
var fields = this.get_fields();
for (var i=0; i<fields.length; i++) {
if (fields[i].enabled && fields[i].dirty) {
return true;
}
}
return false;
},
/**
* Reset all fields
* @fires reset
*/
reset: function() {
var fields = this.get_fields();
for (var i=0; i<fields.length; i++) {
var field = fields[i];
field.reset();
}
this.emit('reset', { source: this });
},
/**
* Validate all fields
* @return {boolean} true when all fields are valid
*/
validate: function() {
var valid = true;
var fields = this.get_fields();
for (var i=0; i<fields.length; i++) {
var field = fields[i];
valid = field.validate() && field.validate_required() && valid;
}
return valid;
},
/** Constructor */
constructor: function(spec) {
this.fields = ordered_map();
var builder_spec = spec.field_builder || field_mod.field_builder;
this.field_builder = builder.build(null, builder_spec);
this.dirty = false;
}
});
return FormMixin;
});

View File

@@ -0,0 +1,426 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/array',
'dojo/_base/lang',
'./construct',
'./Construct_registry',
'./Spec_mod'
], function(declare, array, lang, construct, Construct_registry, Spec_mod) {
var undefined;
/**
* Builder
*
* Builds objects based on their specification.
* @class _base.Builder
*/
var Builder = declare(null, {
/**
* Construct registry
* @property {_base.Construct_registry}
*/
registry: null,
/**
* Specification modifier
* @property {_base.Spec_mod}
*/
spec_mod: null,
/**
* Default factory
* @property {Function|null}
*/
factory: null,
/**
* Default constructor
* @property {Function|null}
*/
ctor: null,
/**
* Array of spec modifiers.
*
* Are applied before build on spec object.
*
* Spec modifier can be:
*
* - a function which is called before build
* - takes params: spec, context
* - returns spec
* - an object which is mixed in into spec
* - an object with properties for Spec_mod
*
* @property {Array|null}
*/
pre_ops: null,
/**
* Array of object modifiers.
*
* Object modifier is a function which is after build.
*
* - takes params: built object, spec, context
* - returns object
* @property {Array|null}
*/
post_ops: null,
/**
* Controls what builder do when spec is a string. Possible values:
*
* - 'type'
* - 'property'
*
* ##Type
* Spec is type. Queries registry for obtaining construction spec.
*
* ##Property
* Spec is a property of spec, name of property is set in
* `string_property`. This mode should be combined with default
* factory or ctor otherwise the build will fail.
*
* @property {string}
*/
string_mode: 'type',
/**
* Property name for `string_mode` == `property`
* @property {string}
*/
string_property: '',
/**
* Build object based on spec.
*
* @param {string|Function|Object|Array} spec Build spec
*
* - **String**: type name, queries registry
* - **Function**: factory or ctor
* - **Object**: spec object
* - **Array**: array of spec objects
*
* Build control properties of spec object:
*
* - $ctor: Function
* - $factory: Function
* - $mixim_spec: boolean
* - $type: string
* - $pre_ops: []
* - $post_ops: []
*
* All other properties will be passed to object construction method.
* @param {Object} context build context
* @param {Object} overrides
* Builder default factory and ctor is overridden by those specified
* in overrides when overrides are set.
*/
build: function(spec, context, overrides) {
var f,c, pre, post;
if (spec === undefined || spec === null) return null;
if (!construct.is_spec(spec)) return spec;
context = context || {};
// save
if (overrides) {
f = this.factory;
c = this.ctor;
pre = this.pre_ops;
post = this.post_ops;
if (typeof overrides === 'function') {
if (construct.is_ctor(overrides)) {
overrides = { $ctor: overrides };
} else {
overrides = { $factory: overrides };
}
}
this.factory = overrides.$factory;
this.ctor = overrides.$ctor;
if (overrides.$pre_ops) this.pre_ops = overrides.$pre_ops;
if (overrides.$post_ops) this.post_ops = overrides.$post_ops;
}
// build
var objects;
if (lang.isArray(spec)) {
objects = [];
for (var i=0; i<spec.length; i++) {
var obj = this._build(spec[i], context);
objects.push(obj);
}
} else {
objects = this._build(spec, context);
}
// restore
if (overrides) {
this.factory = f;
this.ctor = c;
this.pre_ops = pre;
this.post_ops = post;
}
return objects;
},
/**
* Create new construction spec from an existing one based on object
* specification object and save the new construction spec
*
* @param {Object} spec Specification object
* @return {Object} Construction specification
*/
merge_spec: function(spec, force_mixin) {
var cs = {};
if (typeof spec === 'function') {
// spec ctor or factory
if (construct.is_ctor(spec)) {
cs.ctor = spec;
} else {
cs.factory = spec;
}
} else if (typeof spec === 'string') {
// spec is type name or spec property
cs = this._get_cs_string(spec);
} else if (typeof spec === 'object') {
var c = spec.$ctor,
f = spec.$factory,
m = spec.$mixim_spec || force_mixin,
t = spec.$type,
pre = spec.$pre_ops,
post = spec.$post_ops;
var s = lang.mixin({},spec);
delete s.$ctor;
delete s.$factory;
delete s.$mixim_spec;
delete s.$type;
delete s.$pre_ops;
delete s.$post_ops;
if (t) {
cs = this._query_registry(t);
if (cs.spec && m) {
lang.mixin(cs.spec, s);
} else {
cs.spec = s;
}
} else {
cs.spec = s;
}
if (c) cs.ctor = c;
if (f) cs.factory = f;
cs.pre_ops = cs.pre_ops || [];
cs.post_ops = cs.post_ops || [];
if (pre) cs.pre_ops.push.apply(cs.pre_ops, pre);
if (post) cs.post_ops.push.apply(cs.post_ops, post);
}
return cs;
},
/**
* Build single object
* @protected
*/
_build: function(spec, context) {
var cs = this._get_construction_spec(spec);
var obj = this._build_core(cs, context);
return obj;
},
/**
* Normalizes construction specification
* @protected
*/
_get_construction_spec: function(spec) {
var cs = this.merge_spec(spec);
cs.spec = cs.spec || {};
if (!cs.factory && !cs.ctor) {
if (this.ctor) cs.ctor = this.ctor;
else if (this.factory) cs.factory = this.factory;
}
return cs;
},
/**
* Queries registry and returns copy of construction specification
* @protected
*/
_query_registry: function(type) {
if (this.registry) {
var cs = this.registry.get(type);
if (!cs) cs = {};
cs = construct.clone(cs);
return cs;
} else {
throw {
error: 'Build error: construct registry required',
builder: this
};
}
},
/**
* Get cs from string according to string mode
* @protected
*/
_get_cs_string: function(spec) {
var cs;
if (this.string_mode === 'type') {
cs = this._query_registry(spec);
} else {
var sp = {};
sp[this.string_property] = spec;
cs = { spec: sp };
}
return cs;
},
/**
* Core build method
* @protected
*/
_build_core: function(construction_spec, context) {
var cs = construction_spec,
obj = null;
if (!(cs.factory && typeof cs.factory === 'function') &&
!(cs.ctor && typeof cs.ctor === 'function')) {
throw {
error: 'Build error: missing or invalid ctor or factory',
code: 'no-ctor-fac',
spec: cs
};
}
// deep clone to prevent modification of original spec by preops
cs.spec = construct.clone(cs.spec);
cs.spec = this._run_preops(this.pre_ops, cs.spec, context);
if (cs.pre_ops) {
cs.spec = this._run_preops(cs.pre_ops, cs.spec, context);
}
cs.spec = cs.spec || {};
// do we want following?, remove?
this.spec_mod.mod(cs.spec, cs.spec);
this.spec_mod.del_rules(cs.spec);
try {
if (cs.factory) {
obj = cs.factory(cs.spec);
} else {
obj = new cs.ctor(cs.spec);
}
obj = this._run_post_ops(this.post_ops, obj, cs.spec, context);
if (cs.post_ops) {
obj = this._run_post_ops(cs.post_ops, obj, cs.spec, context);
}
} catch (e) {
if (e.expected) {
// expected exceptions thrown by builder just mean that
// object is not to be built
obj = null;
} else {
window.console.error(e.stack);
throw e;
}
}
return obj;
},
/**
* Apply pre_ops
* @protected
*/
_run_preops: function(pre_ops, spec, context) {
for (var i=0; i<pre_ops.length; i++) {
var preop = pre_ops[i];
var preop_t = typeof preop;
if (preop_t === 'function') {
spec = preop(spec, context);
} else if (preop_t === 'object') {
var temp = construct.clone(preop);
this.spec_mod.mod(spec, temp);
this.spec_mod.del_rules(temp);
lang.mixin(spec, temp);
}
}
return spec;
},
/**
* Apply post_ops
* @protected
*/
_run_post_ops: function(post_ops, obj, spec, context) {
for (var i=0; i<post_ops.length; i++) {
var postop = post_ops[i];
var postop_t = typeof postop;
if (postop_t === 'function') {
obj = postop(obj, spec, context);
} else if (postop_t === 'object') {
lang.mixin(obj, postop);
}
}
return obj;
},
/**
* Constructor
*
* set spec.registry to use Construct_registry instance
*/
constructor: function(spec) {
spec = spec || {};
this.pre_ops = [];
this.post_ops = [];
if (spec.factory) this.factory = spec.factory;
if (spec.ctor) this.ctor = spec.ctor;
if (spec.registry) this.registry = spec.registry;
else this.registry = new Construct_registry();
if (spec.spec_mod) this.spec_mod = spec.spec_mod;
else this.spec_mod = new Spec_mod();
if (spec.pre_ops) this.pre_ops.push.call(this.pre_ops, spec.pre_ops);
if (spec.post_ops) this.post_ops.push.call(this.post_ops, spec.post_ops);
}
});
return Builder;
});

View File

@@ -0,0 +1,196 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/array',
'dojo/_base/lang',
'./construct'
], function(declare, array, lang, construct) {
/**
* Registry for storing construction specification.
* @class _base.Construct_registry
*/
var Construct_registry = declare(null, {
/**
* Internal map for construction specifications.
* @protected
*/
_map: null,
/**
* Registers construction specification
*
* // May be defined by single construction spec object:
* var construction_spec = {
* type: String,
* factory: Function,
* ctor: Function,
* spec: Object,
* pre_ops: [],
* post_ops: []
* };
* register(construction_spec);
*
* // or by defining them separately as params:
* register(type, factory|ctor, spec);
*
* @param {string|Object} type type or construction spec
* @param {Function} func ctor or factory function
* @param {Object} [default_spec] default spec object for given type
*
* @returns {Object}
*/
register: function(type, func, default_spec) {
var cs, f, c;
if (typeof type === 'object') {
cs = type;
} else {
construct.is_ctor(func) ? c = func : f = func;
cs = {
type: type,
factory: f,
ctor: c,
spec: default_spec
};
}
if (!cs.pre_ops) cs.pre_ops = [];
if (!cs.post_ops) cs.post_ops = [];
this._check_spec(cs);
this._map[cs.type] = cs;
return cs;
},
/**
* Makes a copy of construct specification of original type. Extends
* it with values in supplied construct specification.
*
* @param {string} org_type Original type
* @param {string} new_type New type
* @param {Object} construct_spec Construction specification
*/
copy: function(org_type, new_type, construct_spec) {
var def_cs = construct_spec;
var old_cs = this._check_get(org_type);
var cs = construct.clone(old_cs);
cs.type = new_type;
if (def_cs.pre_ops) cs.pre_ops.push.apply(cs.pre_ops, def_cs.pre_ops);
if (def_cs.post_ops) cs.post_ops.push.apply(cs.post_ops, def_cs.post_ops);
if (def_cs.factory) cs.factory = def_cs.factory;
if (def_cs.ctor) cs.ctor = def_cs.ctor;
if (def_cs.spec) {
cs.spec = cs.spec || {};
lang.mixin(cs.spec, def_cs.spec);
}
this._check_spec(cs);
this._map[cs.type] = cs;
return cs;
},
/**
* Registers pre operation.
*
* Purpose of pre operation is to modify spec object before build
* operation.
*
* When op is Function it gets called with spec as a param and should
* return modified spec.
*
* When op is Object, the object gets mixed in into spec.
*
* @param {string} type
* @param {Function|Object} op
* @param {boolean} move op to first position
*/
register_pre_op: function(type, op, first) {
var cs = this._check_get(type);
if (first) cs.pre_ops.unshift(op);
else cs.pre_ops.push(op);
},
/**
* Registers post operation.
*
* Purpose of post operation is to modify built object.
*
* When op is Function it gets called with built object as a param
* and should return modified obj.
*
* When op is Object, the object gets mixed in into built object. Use
* with caution.
*
* @param {string} type
* @param {Function|Object} op
* @param {boolean} first move op to first position
*/
register_post_op: function(type, op, first) {
var cs = this._check_get(type);
if (first) cs.post_ops.unshift(op);
else cs.post_ops.push(op);
},
/**
* Gets construction specification for given type.
*
* @param {string} string Type name
* @returns {Object|null}
*/
get: function(type) {
return this._map[type] || null;
},
_check_get: function(type) {
var cs = this.get(type);
if (!cs) throw construct.no_cs_for_type_error(type);
return cs;
},
_check_spec: function(spec) {
if (typeof spec.type !== 'string' || spec.type === '') {
throw 'Argument exception: Invalid type';
}
if (!lang.isArrayLike(spec.pre_ops)) {
throw 'Argument exception: Invalid pre_ops type.';
}
if (!lang.isArrayLike(spec.post_ops)) {
throw 'Argument exception: Invalid post_ops type.';
}
},
constructor: function(spec) {
this._map = {};
}
});
return Construct_registry;
});

View File

@@ -0,0 +1,258 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/array',
'dojo/_base/declare',
'dojo/Deferred',
'dojo/promise/all',
'dojo/topic',
'../ordered-map'
], function(array, declare, Deferred, all, topic, ordered_map) {
/**
* Phase
*
* This class does not exist, it's only for documentation purposes.
*
* @class _base.Phase_controller.phase
* @abstract
*/
/**
* Name
* @property {string} name
*/
/**
* Tasks
* @property {Array.<_base.Phase_controller.task>} tasks
*/
/**
* Phase task
*
* This class does not exist, it's only for documentation purposes.
*
* @class _base.Phase_controller.task
* @abstract
*/
/**
* Name
* @property {number} priority
*/
/**
* Tasks
* @property {Function} handler
*/
/**
* Phase Controller
*
* Creates synchronization points - phases - in application life cycle.
*
* Phases:
*
* - are ordered
* - consist of task
* - phase finishes when all task finishes
* - new phases can be added at runtime
*
* @class _base.Phase_controller
*/
var Phase_controller = declare(null, {
/**
* Phases
* @property {ordered_map.<string, _base.Phase_controller.phase>}
*/
phases: null,
/**
* Current phase name
* @property {string}
*/
current: null,
/**
* Run all phases in a row starting from current, or the first when
* current is not set.
*/
run: function() {
if (this.current !== null) {
var phase = this.phases.get(this.current);
this._run_phase(phase);
} else {
this.next_phase(true);
}
},
/**
* Runs phase
*
* 1. Sorts tasks of the phase based on their priority.
* 2. Runs all task sequentially.
* 3. Waits for all tasks to complete (in case of asynchronous ones)
* 4. Optionally runs next phase
*
* @param {_base.Phase_controller.phase} phase Phase to run
* @param {boolean} next_phase Whether to run next phase when current finishes
*/
_run_phase: function(phase, next_phase) {
if (!phase) return;
this.current = phase.name;
topic.publish('phase-start', { phase: phase.name });
var promises = [];
var tasks = phase.tasks.sort(function(a,b) {
return a.priority-b.priority;
});
array.forEach(tasks, function(task) {
var promise;
try {
promise = task.handler();
} catch (e) {
var fail = new Deferred();
fail.reject(e, true);
promise = fail.promise;
}
promises.push(promise);
});
all(promises).then(function(results) {
topic.publish('phase-finished',
{ phase: phase.name, results: results });
if (next_phase) {
this.next_phase(next_phase);
}
}.bind(this), function(results) {
topic.publish('phase-error',
{ phase: phase.name, results: results });
// don't go for next phase on error, let app decide what to do
});
},
/**
* Selects next phase and then runs it.
*
* @param {boolean} continuous Whether to run phases continuously
*/
next_phase: function(continuous) {
var phase;
if (this.current === null) {
phase = this.phases.get_value_by_index(0);
} else {
var index = this.phases.get_key_index(this.current);
phase = this.phases.get_value_by_index(index + 1);
}
this._run_phase(phase, continuous);
},
/**
* Adds task for a phase.
*
* At phase execution, tasks are sorted by priority and executed in
* that order.
*
* @param {string} phase_name Name of associated phase
* @param {Function} handler Task handler. Should return promise if async.
* @param {number} [priority=10] Priority of task.
*/
add_task: function(phase_name, handler, priority) {
var phase = this.phases.get(phase_name);
if (!phase) {
window.console.warn('no such phase: ' + phase_name);
return;
}
if (typeof priority !== 'number') priority = 10;
phase.tasks.push({
priority: priority,
handler: handler
});
},
/**
* Adds a phase
*
* Possible options:
*
* - before: 'name-of-phase'
* - after: 'name-of-phase'
* - position: 'position for new phase'
*
* @param {string} phase name
* @param {Array.<_base.Phase_controller.task>} tasks
* @param {Object} options
*/
add_phase: function(name, tasks, options) {
var phase = {
name: name,
tasks: tasks || []
};
var position;
if (options) {
if (options.before) {
position = this.phases.get_key_index(options.before);
} else if (options.after) {
position = this.phases.get_key_index(options.after);
if (position === -1) position = this.phases.length;
else position++;
} else if (options.position) {
position = options.position;
}
}
this.phases.put(name, phase, position);
},
/**
* Checks if phases with given name exists
*
* @param {string} name
* @return {boolean}
*/
exists: function(name) {
return !!this.phases.get(name);
},
constructor: function(spec) {
spec = spec || {};
this.phases = ordered_map();
var phases = spec.phases || [];
array.forEach(phases, function(phase) {
this.add_phase(phase);
}.bind(this));
}
});
return Phase_controller;
});

View File

@@ -0,0 +1,230 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Value provider.
*
* It search source or child providers for value defined by key.
*
* Key consists of code and path.
*
* Code defines the type of resource. Provider's handles() method tells whether
* it can handle this type of resource.
*
* Path is a plain object path within a source.
*
* // if source is
* {
* foo: {
* bar: {
* a: 'val'
* }
* }
* }
*
* // path: `foo.bar.a` would return `val`
*
* @class _base.Provider
*
*/
define([
'dojo/_base/declare',
'dojo/_base/lang',
'./debug'],
function(declare, lang, debug) {
var undefined;
var Provider = declare(null, {
/**
* Array of other providers
* @property {_base.Provider[]}
*/
providers: null,
/**
* Source object or a function which returns source object.
* @property {Function|Object|_base.Provider}
*/
source: null,
/**
* Path within a source.
*
* When defined, all lookups in source are based on the object
* defined by this path within a source.
* @property {string}
*/
path: null,
/**
* Value which is returned if no value nor alternative is found
* @property {Mixed}
*/
null_value: null,
/**
* Specifies which type should be returned. Limited to output of
* typeof operator.
* @property {string}
*/
required_type: null,
_code: null,
_code_length: null,
_handling_provider: null,
_set_code: function(code) {
this._code = code;
if (code) this._code_length = code.length;
},
_get_source: function() {
var source;
var type = typeof this.source;
if (type === 'function') {
source = this.source.call(this);
} else if (type === 'object') {
source = this.source;
// if source is another provider, use its source as this source
if (source.isInstanceOf && source.isInstanceOf(Provider) &&
source.source) {
source = source._get_source();
}
}
if (this.path) {
source = lang.getObject(this.path, false, source);
}
return source;
},
_handles: function(key) {
if (!this._code) return false;
if (typeof key !== 'string') return false;
if (key[0] !== '@') return false;
var code = key.substring(0, this._code_length);
var handles = code === this._code;
return handles;
},
_handle_children: function(key) {
var handles = false;
this._handling_provider = null;
for (var i=0; i< this.providers.length; i++) {
handles = this.providers[i].handles(key);
if (handles) {
this._handling_provider = this.providers[i];
break;
}
}
return handles;
},
/**
* Get's value from this provider's source
* @protected
*/
_get: function(key) {
var property = key.substring(this._code_length);
var value = lang.getObject(property, false, this._get_source());
return value;
},
/**
* Finds out whether this or some of its children handles given key.
*/
handles: function(key) {
var handles = this._handles(key);
handles = handles || this._handle_children(key);
return handles;
},
/**
* Gets value.
*
* @param {string|Object} Key or value
* @param {Object} Alternate value
*/
get: function(key, alternate) {
var value = key;
if (key !== undefined) {
if (this._handles(key)) {
value = this._get(key);
} else if(this._handle_children(key)) {
value = this._handling_provider.get(key);
} else {
// Report invalid keys
if (typeof key === 'string' && key[0] === '@') {
window.console.warn('Using key as value:'+key);
}
}
}
var ret = value || alternate;
if (!ret && key && debug.provider_missing_value) {
window.console.log('No value for:'+key);
}
if ((this.required_type && typeof ret !== this.required_type) ||
ret === null ||
ret === undefined){
ret = this.null_value;
}
return ret;
},
/**
* Finds object with attr_name === value in array defined by key.
*/
find: function(key, attr_name, value) {
var arr = this.get(key);
if (!lang.isArrayLike(arr)) return null;
for (var i=0; i<arr.length; i++) {
if (arr[i][attr_name] === value) {
return arr[i];
}
}
return null;
},
constructor: function(spec) {
spec = spec || {};
this.source = spec.source || {};
this.path = spec.path || null;
this.providers = spec.providers || [];
if (spec.null_value !== undefined) {
this.null_value = spec.null_value;
}
this.required_type = spec.required_type;
if (spec.code) {
this._set_code(spec.code);
}
}
});
return Provider;
});

View File

@@ -0,0 +1,122 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Search value provider
*
* Serves for searching for values within an array in a source object.
*
* Path has input formats as follows:
*
* * key1:key2:key3
* * key1:key2
* * key2
*
* With:
*
* * base_query: `%1.takes_params`
* * array_attr: `name`
*
* Such path is translates into query:
*
* * `%key1.takes_params[name=%key2].$key3`
*
* In a future we should support defining generic queries and thus not be
* limited to simple search.
*
* @class _base.Search_provider
* @extends _base.Provider
*/
define(['dojo/_base/declare','dojo/_base/lang', './Provider'],
function(declare, lang, Provider) {
var Search_provider = declare([Provider], {
base_query: null,
array_attr: null,
/**
* @inheritDoc
* @protected
*/
_get: function(key) {
var search_keys = key.substring(this._code_length);
search_keys = search_keys.split(':');
var count = search_keys.length;
if (count < 1 || count > 3) return null;
var key1, key2, key3;
if (count === 1) {
key2 = search_keys[0];
} else if (count === 2) {
key1 = search_keys[0];
key2 = search_keys[1];
} else {
key1 = search_keys[0];
key2 = search_keys[1];
key3 = search_keys[2];
}
var arr;
var source = arr = this._get_source();
if (key1) {
var property = this.base_query.replace('%1', search_keys[0]);
arr = lang.getObject(property, false, source);
}
var ret = this._find(arr, this.array_attr, key2, false);
if (ret && key3) {
ret = lang.getObject(key3, false, ret);
}
return ret;
},
/**
* Finds object with attr_name === value in array defined by key.
* @protected
*/
_find: function(array, attr, value, all) {
var vals = [];
if (!lang.isArrayLike(array)) return null;
for (var i=0; i<array.length; i++) {
if (array[i][attr] === value) {
vals.push(array[i]);
if (!all) break;
}
}
if (!all) return vals[0] || null;
return vals;
},
constructor: function(spec) {
spec = spec || {};
this.base_query = spec.base_query || '%1';
this.array_attr = spec.array_attr || 'name';
}
});
return Search_provider;
});

View File

@@ -0,0 +1,168 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/array',
'dojo/_base/lang',
'./construct',
'./Builder',
'./Construct_registry'
], function(declare, array, lang, construct, Builder, Construct_registry) {
/**
* Registry for storing singleton instances of various items based
* on their type.
*
* @class _base.Singleton_registry
*/
var Singleton_registry = declare(null, {
/**
* Internal map for instances
* @protected
* @property {Object}
*/
_map: {},
/**
* Builder used for building new instances. Builder has to have a
* Constructor registry set.
* @property {_base.Builder}
*/
builder: null,
/**
* Gets an instance of given type. Creates a new one if it doesn't
* exist.
*
* When an object is passed in, the function returns it.
*
* @param {string|Object} type Type's name. Or the object itself.
* @return {Object|null}
*/
get: function(type) {
if (typeof type === 'object') return type;
var obj = this._map[type];
if (!obj) {
if (!this.builder) return null;
try {
obj = this._map[type] = this.builder.build(type);
} catch (e) {
if (e.code === 'no-ctor-fac') obj = null;
else {
window.console.error('Error while building: ' + type);
throw e;
}
}
}
return obj;
},
/**
* Set object of given type - overwrites existing
*
* @param {string} type
* @param {Mixed} object
*/
set: function (type, obj) {
this._map[type] = obj;
},
/**
* Removes object of given type from registry
*
* @param {string} type
*/
remove: function(type) {
var undefined;
this._map[type] = undefined;
},
/**
* Registers construction specification
*
* @param {string|Object} type type or construction spec
* @param {Function} func ctor or factory function
* @param {Object} [default_spec] default spec object for given type
*
* @return {Object}
*/
register: function(type, func, default_spec) {
this._check_builder();
this.builder.registry.register(type, func, default_spec);
},
/**
* Makes a copy of construct specification of original type. Extends
* it with values in supplied construct specification.
*
* @param {string} org_type Original type
* @param {string} new_type New type
* @param {Object} construct_spec Construction specification
*/
copy: function(org_type, new_type, construct_spec) {
this._check_builder();
this.builder.registry.copy(org_type, new_type, construct_spec);
},
/**
* Create new construction specification based on an existing one and
* a specification object. Save it as a new type.
* @param {string|Function} type New type or a callback to get
* the type: `callback(spec)`
* @param {Object} spec Construction specification
*/
register_from_spec: function(type, spec) {
this._check_builder();
var cs = this.builder.merge_spec(spec, true);
if (typeof type === 'function') {
cs.type = type(cs.spec);
} else {
cs.type = type;
}
this.builder.registry.register(cs);
},
_check_builder: function() {
if (!lang.exists('builder.registry', this)) {
throw {
error: 'Object Initialized Exception: builder not initalized',
context: this
};
}
},
constructor: function(spec) {
spec = spec || {};
this._map = {};
this.builder = spec.builder || new Builder({
registry: new Construct_registry()
});
}
});
return Singleton_registry;
});

View File

@@ -0,0 +1,242 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/lang'
], function(declare, lang) {
/**
* Utility for common modification of specification objects
*
* @class _base.Spec_mod
*/
var Spec_mod = declare(null, {
/**
* Modifies spec according to rules defined in diff object.
*
* Diff should have structure as follows:
*
* {
* $add: array of add rules
* $del: array of del rules
* $set: array of set rules
* $replace: array of replace rules
* }
*
* The order of modification is del, add, set, replace.
*
* @param {Object} spec
* @param {Object} diff
*/
mod: function(spec, diff) {
if (!diff) return spec;
this.del(spec, diff.$del);
this.add(spec, diff.$add);
this.set(spec, diff.$set);
this.replace(spec, diff.$replace);
return spec;
},
/**
* Adds objects according to rules to array.
*
* A rule is a triple of path and a object and position to add:
*
* ['path.to.spec.array', {}, position]
* @param {Object} spec
* @param {Array} rules
*/
add: function(spec, rules) {
return this._apply_rules(spec, rules, this._add);
},
/**
* Deletes objects according to rules from an array.
*
* A rule is a pair of path and delete conditions:
*
* ['path.to.spec.array', [ { name: 'foo'}, { name: 'baz'} ]]
* // Deletes all objects with name 'baz' or 'foo'.
* @param {Object} spec
* @param {Array} rules
*/
del: function(spec, rules) {
return this._apply_rules(spec, rules, this._del);
},
/**
* A rule is a pair of path and a object to set.
*
* ['path.to.spec.property', {}]
* @param {Object} spec
* @param {Array} rules
*/
set: function(spec, rules) {
return this._apply_rules(spec, rules, this._set);
},
/**
* Replace objects in an arrays
*
* A rule is a pair of path to an array and a objects to replace in that array
*
* [
* 'path.to.spec.array',
* [
* [match, new_obj_spec],
* [match2, new_obj_spec_2],
* ...
* ]
* ]
* Example of replacement specs:
*
* ['add', { name: 'add', hide_cond: [] }]
* [{ name: 'add' }, { name: 'add', hide_cond: [] }]
* @param {Object} spec
* @param {Array} rules
*/
replace: function(spec, rules) {
return this._apply_rules(spec, rules, this._replace);
},
/**
* Removes all rule props
* @param {Object} diff
*/
del_rules: function(diff) {
delete diff.$add;
delete diff.$del;
delete diff.$set;
delete diff.$replace;
},
_apply_rules: function(spec, rules, method) {
if (!lang.isArrayLike(rules)) return spec;
for (var i=0; i<rules.length; i++) {
method.call(this, spec, rules[i]);
}
return spec;
},
_add: function(spec, rule) {
var path = rule[0];
var value = rule[1];
var pos = rule[2];
var arr = lang.getObject(path, false, spec);
if (!arr) {
arr = [];
lang.setObject(path, arr, spec);
}
if (typeof pos !== 'number') pos = arr.length;
else if (pos < 0) pos = 0;
else if (pos > arr.length) pos = arr.length;
arr.splice(pos, 0, value);
return spec;
},
_del: function(spec, rule) {
var path = rule[0];
var conds = rule[1];
var arr = lang.getObject(path, false, spec);
if (!arr) return spec;
var del = [];
var i,j;
for (i=0; i<arr.length; i++) {
for (j=0; j<conds.length; j++) {
if (this._match(arr[i], conds[j])) {
del.push(i);
break;
}
}
}
del.sort(function(a,b) {return b-a;});
for (i=0; i<del.length;i++) {
arr.splice(del[i], 1);
}
return spec;
},
_replace: function(spec, rule) {
var path = rule[0];
var replace_rules = rule[1];
var arr = lang.getObject(path, false, spec);
if (!arr) return spec;
for (var i=0; i<replace_rules.length; i++) {
var conds = replace_rules[i][0];
var new_spec = replace_rules[i][1];
for (var j=0; j<arr.length; j++) {
if (this._match(arr[j], conds)) {
arr[j] = new_spec;
break;
}
}
}
return spec;
},
_match: function(value, cond) {
var match = true;
if (typeof cond !== 'object') {
match = cond === value;
} else {
for (var prop in cond) {
if (cond.hasOwnProperty(prop) && cond[prop] !== value[prop]) {
match = false;
break;
}
}
}
return match;
},
_set: function(spec, rule) {
lang.setObject(rule[0], rule[1], spec);
return spec;
}
});
return Spec_mod;
});

View File

@@ -0,0 +1,126 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/array',
'dojo/_base/lang'
], function(declare, array, lang) {
/**
* Helper module
* @class _base.construct
* @singleton
*/
var construct = {
/**
* Checks if supplied object is a constructor function.
* It can recognize only classes declared by `dojo/_base/declare`.
* @param {Object} obj
*/
is_ctor: function(obj) {
return typeof obj === 'function' && typeof obj.extend === 'function';
},
/**
* Finds out if object is a spec object.
*
* Object is not a spec object when it has an `isInstanceOf` function.
*
* @param {Object} obj
*/
is_spec: function(obj) {
var ret = false;
if (typeof obj === 'object') {
ret = typeof obj.isInstanceOf === 'function';
}
return !ret;
},
/**
* Deep clone
*
* - does not clone framework objects
* - fails on cyclic non-framework objects
*
* based on `dojo/_base/lang.clone`
*
* @param {Mixed} src object to clone
*/
clone: function(src) {
if(!src || typeof src != "object" || lang.isFunction(src)) {
// null, undefined, any non-object, or function
return src; // anything
}
if(src.nodeType && "cloneNode" in src) {
// DOM Node
return src.cloneNode(true); // Node
}
if (!construct.is_spec(src)) {
// framework object
return src;
}
if (src instanceof Date) {
// Date
return new Date(src.getTime()); // Date
}
if (src instanceof RegExp) {
// RegExp
return new RegExp(src); // RegExp
}
var r, i, l;
if (lang.isArray(src)){
// array
r = [];
for (i = 0, l = src.length; i < l; ++i) {
if (i in src){
r.push(construct.clone(src[i]));
}
}
} else {
// generic objects
r = src.constructor ? new src.constructor() : {};
}
return lang._mixin(r, src, construct.clone);
},
/**
* Run object's init function after instantiation if it has one
* @param {Object} obj
* @param {Object} spec
*/
init_post_op: function(obj, spec) {
if (obj && typeof obj.init === 'function') {
obj.init(spec);
}
return obj;
},
no_cs_for_type_error: function(type) {
return {
error: 'No construction specification for given type',
type: type
};
}
};
return construct;
});

View File

@@ -0,0 +1,41 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2014 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([], function() {
/**
* Debug module
*
* One can set flags to enable console output of various messages.
*
* """
* var debug = require('freeipa._base.debug');
* debug.provider_missing_value = true;
* """
*
* Currently used flags
*
* - provider_missing_value
*
* @class _base.debug
*/
return {
provider_missing_value: false
};
});

View File

@@ -0,0 +1,42 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Gets translated message.
*
* If a message starts with `@i18n`: it tries to get the message from
* message object. If it doesn't contain a string with
* the key it returns alternate string.
*
* It all other cases the message itself or empty string is returned.
* @class _base.i18n
* @extends _base.Provider
* @singleton
*/
define(['dojo/_base/lang', './Provider'], function(lang, Provider) {
var i18n = new Provider({
code: '@i18n:',
null_value: '',
required_type: 'string'
});
return i18n;
});

View File

@@ -0,0 +1,972 @@
/* Authors:
* Adam Young <ayoung@redhat.com>
* Endi S. Dewata <edewata@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/on',
'./metadata',
'./ipa',
'./jquery',
'./phases',
'./reg',
'./text',
'./details',
'./search',
'./association',
'./entity'],
function(on, metadata_provider, IPA, $, phases, reg, text) {
/**
* Widgets, entities and fields related to Access Control that means
* Permissions, Privilege, Role, Delegation and Self-service.
*
* @class aci
* @singleton
*/
var aci = {};
/**
* List of fields which are disabled for managed permissions
* @property {Array}
*/
aci.managed_fields = [
'ipapermright', 'extratargetfilter', 'memberof', 'ipapermlocation',
'ipapermtarget', 'type'
];
var make_permission_spec = function() {
return {
name: 'permission',
facet_groups: ['settings', 'privilege'],
facets: [
{
$type: 'search',
columns: [ 'cn' ]
},
{
$factory: aci.permission_details_facet,
$type: 'details',
fields: [
{
name:'cn',
widget: 'identity.cn'
},
{
$type: 'radio',
name:'ipapermbindruletype',
widget: 'identity.ipapermbindruletype',
flags: ['w_if_no_aci']
},
{
$type: 'rights',
name: 'ipapermright',
widget: 'identity.ipapermright',
required: true,
flags: ['w_if_no_aci']
},
{
$type: 'multivalued',
name: 'extratargetfilter',
widget: 'target.extratargetfilter',
acl_param: 'ipapermtargetfilter',
enabled: false,
flags: ['w_if_no_aci']
},
{
$type: 'multivalued',
name: 'memberof',
widget: 'target.memberof',
enabled: false,
flags: ['w_if_no_aci']
},
{
name: 'ipapermlocation',
widget: 'target.ipapermlocation',
enabled: false,
flags: ['w_if_no_aci']
},
{
name: 'ipapermtarget',
widget: 'target.ipapermtarget',
enabled: false,
flags: ['w_if_no_aci']
},
{
$type: 'select',
name: 'type',
widget: 'target.type',
enabled: false,
flags: ['w_if_no_aci']
},
{
name: 'attrs',
widget: 'target.attrs',
enabled: false,
flags: ['w_if_no_aci']
},
{
name: 'attrs_multi',
param: 'attrs',
$type: 'multivalued',
widget: 'target.attrs_multi',
enabled: false,
flags: ['w_if_no_aci']
},
{
name: 'ipapermdefaultattr',
$type: 'multivalued',
widget: 'managed.ipapermdefaultattr'
},
{
name: 'ipapermincludedattr',
$type: 'multivalued',
widget: 'managed.ipapermincludedattr',
read_only: true
},
{
name: 'ipapermexcludedattr',
$type: 'multivalued',
widget: 'managed.ipapermexcludedattr',
read_only: true
}
],
widgets: [
{
$type: 'details_section',
name: 'identity',
label: '@i18n:objects.permission.identity',
widgets: [
'cn',
{
$type: 'radio',
name: 'ipapermbindruletype',
options: ['permission', 'all', 'anonymous']
},
{
$type: 'rights',
name: 'ipapermright',
layout: 'columns'
}
]
},
{
$type: 'permission_target',
container_factory: IPA.details_section,
label: '@i18n:objects.permission.target',
name: 'target'
},
{
$type: 'details_section',
name: 'managed',
label: '@i18n:objects.permission.managed',
widgets: [
{
$type: 'multivalued',
name: 'ipapermdefaultattr'
},
{
$type: 'multivalued',
name: 'ipapermincludedattr'
},
{
$type: 'multivalued',
name: 'ipapermexcludedattr'
}
]
}
],
policies: [
aci.permission_managed_policy,
{
$factory: aci.permission_target_policy,
widget_name: 'target'
}
]
},
{
$type: 'association',
name: 'member_privilege',
facet_group: 'privilege'
}
],
adder_dialog: {
height: 450,
fields: [
{
name:'cn',
widget: 'general.cn'
},
{
$type: 'radio',
name:'ipapermbindruletype',
widget: 'general.ipapermbindruletype'
},
{
$type: 'rights',
name: 'ipapermright',
widget: 'general.ipapermright',
required: true
},
{
$type: 'multivalued',
name: 'extratargetfilter',
widget: 'target.extratargetfilter',
acl_param: 'ipapermtargetfilter',
enabled: false
},
{
$type: 'multivalued',
name: 'memberof',
widget: 'target.memberof',
enabled: false
},
{
name: 'ipapermlocation',
widget: 'target.ipapermlocation',
enabled: false
},
{
name: 'ipapermtarget',
widget: 'target.ipapermtarget',
enabled: false
},
{
$type: 'select',
name: 'type',
widget: 'target.type',
enabled: false
},
{
name: 'attrs',
widget: 'target.attrs',
enabled: false
},
{
name: 'attrs_multi',
$type: 'multivalued',
param: 'attrs',
widget: 'target.attrs_multi',
enabled: false
}
],
widgets: [
{
$type: 'details_section',
name: 'general',
widgets: [
'cn',
{
$type: 'radio',
name: 'ipapermbindruletype',
options: ['permission', 'all', 'anonymous'],
default_value: 'permission'
},
{
$type: 'rights',
name: 'ipapermright',
layout: 'columns'
}
]
},
{
$type: 'permission_target',
name:'target'
}
],
policies: [
{
$factory: aci.permission_target_policy,
widget_name: 'target'
}
]
}
};};
/**
* @class aci.permission_details_facet
* @extends details.details_facet
*/
aci.permission_details_facet = function(spec) {
var that = IPA.details_facet(spec);
that.get_refresh_command_name = function() {
return that.entity.name+'_show_'+that.get_pkey();
};
return that;
};
var make_privilege_spec = function() {
return {
name: 'privilege',
facet_groups: ['permission', 'settings', 'role'],
facets: [
{
$type: 'search',
columns: [
'cn',
'description'
]
},
{
$type: 'details',
sections: [
{
name: 'identity',
label: '@i18n:details.identity',
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
]
},
{
$type: 'association',
name: 'member_role',
facet_group: 'role',
add_method: 'add_privilege',
remove_method: 'remove_privilege',
associator: IPA.serial_associator
},
{
$type: 'association',
name: 'memberof_permission',
facet_group: 'permission',
add_method: 'add_permission',
remove_method: 'remove_permission'
}
],
standard_association_facets: true,
adder_dialog: {
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
};};
var make_role_spec = function() {
return {
name: 'role',
facet_groups: ['member', 'privilege', 'settings'],
facets: [
{
$type: 'search',
columns: [
'cn',
'description'
]
},
{
$type: 'details',
sections: [
{
name: 'identity',
label: '@i18n:objects.role.identity',
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
]
},
{
$type: 'association',
name: 'memberof_privilege',
facet_group: 'privilege',
add_method: 'add_privilege',
remove_method: 'remove_privilege'
}
],
standard_association_facets: true,
adder_dialog: {
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
};};
var make_selfservice_spec = function() {
return {
name: 'selfservice',
facets: [
{
$type: 'search',
columns: [ 'aciname' ],
pagination: false
},
{
$type: 'details',
check_rights: false,
sections: [
{
name: 'general',
label: '@i18n:details.general',
fields: [
'aciname',
{
$type: 'attributes',
object_type: 'user',
name: 'attrs'
}
]
}
]
}
],
adder_dialog: {
fields: [
'aciname',
{
$type: 'attributes',
object_type: 'user',
name: 'attrs'
}
]
}
};};
var make_delegation_spec = function() {
return {
name: 'delegation',
facets: [
{
$type: 'search',
columns: [ 'aciname' ],
pagination: false
},
{
$type: 'details',
check_rights: false,
sections: [
{
name: 'general',
label: '@i18n:details.general',
fields: [
'aciname',
{
$type: 'checkboxes',
name: 'permissions',
required: true,
options: IPA.create_options(['read', 'write'])
},
{
$type: 'entity_select',
name: 'group',
other_entity: 'group',
other_field: 'cn'
},
{
$type: 'entity_select',
name: 'memberof',
other_entity: 'group',
other_field: 'cn'
},
{
$type: 'attributes',
name: 'attrs',
object_type: 'user'
}
]
}
]
}
],
standard_association_facets: false,
adder_dialog: {
fields: [
'aciname',
{
$type: 'checkboxes',
name: 'permissions',
options: IPA.create_options(['read', 'write'])
},
{
$type: 'entity_select',
name: 'group',
other_entity: 'group',
other_field: 'cn'
},
{
$type: 'entity_select',
name: 'memberof',
other_entity: 'group',
other_field: 'cn'
},
{
$type: 'attributes',
name: 'attrs',
object_type: 'user'
}
]
}
};};
aci.attributes_widget = function(spec) {
spec = spec || {};
spec.layout = spec.layout || 'columns attribute_widget';
spec.add_dialog_title = spec.add_dialog_title ||
"@i18n:objects.permission.add_custom_attr";
spec.add_field_label = spec.add_field_label ||
'@i18n:objects.permission.attribute';
spec.set_value_to_lowercase = spec.set_value_to_lowercase === undefined ?
true : spec.set_value_to_lowercase;
var that = IPA.custom_checkboxes_widget(spec);
that.object_type = spec.object_type;
that.populate = function() {
if (!that.object_type || that.object_type === '') return;
var metadata = metadata_provider.get('@mo:'+that.object_type);
if (!metadata) return;
var aciattrs = metadata.aciattrs;
that.options = that.prepare_options(aciattrs);
};
return that;
};
/**
* @class aci.rights_widget
* @extends IPA.checkboxes_widget
*/
aci.rights_widget = function(spec) {
var that = IPA.checkboxes_widget(spec);
that.rights = ['read', 'search', 'compare', 'write', 'add', 'delete', 'all'];
for (var i=0; i<that.rights.length; i++) {
var right = that.rights[i];
that.add_option({label: right, value: right});
}
return that;
};
/**
* Default target to display in `permission_target_widget`
* @property {string}
*/
aci.default_target = 'general';
/**
* @class aci.permission_target_widget
* @extends IPA.details_section
*/
aci.permission_target_widget = function(spec) {
spec = spec || {};
var factory = spec.container_factory || IPA.details_section;
var that = factory(spec);
that.group_entity = IPA.get_entity(spec.group_entity || 'group');
that.target = aci.default_target;
var init = function() {
var objects = metadata_provider.get('@m:objects');
var types = IPA.create_options(['']);
for (var o in objects) {
if (objects.hasOwnProperty(o)) {
var obj = objects[o];
if (obj.can_have_permissions) {
types.push({
label: obj.label_singular,
value: o
});
}
}
}
that.type_select = IPA.select_widget({
entity: that.entity,
name: 'type',
visible: false,
options: types
});
that.widgets.add_widget(that.type_select);
that.ipapermlocation_text = IPA.text_widget({
entity: that.entity,
name: 'ipapermlocation',
visible: false
});
that.widgets.add_widget(that.ipapermlocation_text);
that.extratargetfilter_text = IPA.multivalued_widget({
entity: that.entity,
name: 'extratargetfilter',
visible: false
});
that.widgets.add_widget(that.extratargetfilter_text);
that.ipapermtarget_text = IPA.text_widget({
entity: that.entity,
name: 'ipapermtarget',
visible: false
});
that.widgets.add_widget(that.ipapermtarget_text);
that.memberof_select = IPA.multivalued_widget({
name: 'memberof',
entity: that.entity,
hidden: true,
child_spec: {
$type: 'entity_select',
other_entity: that.group_entity,
other_field: 'cn'
}
});
that.widgets.add_widget(that.memberof_select);
that.attribute_table = aci.attributes_widget({
entity: that.entity,
name: 'attrs',
object_type: types[0].name,
visible: false
});
that.widgets.add_widget(that.attribute_table);
that.attribute_multivalued = IPA.multivalued_widget({
entity: that.entity,
name: 'attrs_multi',
visible: false
});
that.widgets.add_widget(that.attribute_multivalued);
};
init();
return that;
};
/**
* Permission target policy
* @class aci.permission_target_policy
* @extends IPA.facet_policy
*/
aci.permission_target_policy = function (spec) {
var that = IPA.facet_policy();
that.widget_name = spec.widget_name;
that.managed = false;
that.init = function() {
that.permission_target = that.container.widgets.get_widget(that.widget_name);
var type_f = that.container.fields.get_field('type');
on(type_f, 'value-change', that.apply_type);
};
that.apply_type = function () {
var widgets = that.permission_target.widgets;
var type_select = widgets.get_widget('type');
var type = type_select.save()[0];
var new_target = type === '' ? 'general' : 'type';
if (that.permission_target.target !== new_target) {
var attr_table = widgets.get_widget('attrs');
var attr_multi = widgets.get_widget('attrs_multi');
var loc_w = widgets.get_widget('ipapermlocation');
var loc_f = that.container.fields.get_field('ipapermlocation');
var attrs;
that.select_target(new_target);
if (new_target === 'general') {
attrs = attr_table.save();
attr_multi.update(attrs);
attr_multi.value_changed.notify([], attr_multi);
// permission plugin resets ipapermlocation to basedn when
// type is unset. -> use it as pristine value so undo will
// work correctly.
loc_f.set_value([IPA.env.basedn], true);
} else {
attrs = attr_multi.save();
attr_table.update(attrs);
// notification will be done by `set_attrs_type`
}
}
that.set_attrs_type(type, true);
};
that.set_attrs_type = function(type, skip_unmatched) {
var attribute_field = that.container.fields.get_field('attrs');
var attribute_table = that.permission_target.widgets.get_widget('attrs');
var skip_unmatched_org = attribute_table.skip_unmatched;
attribute_table.object_type = type;
// UI doesn't always know what are the possible attributes.
// In case of managed permissions, one of the possible lists is in ipapermdefaultattr.
var default_attrs = that.container.fields.get_field('ipapermdefaultattr');
if (default_attrs && default_attrs.enabled) { // if managed permission
attribute_table.custom_options = default_attrs.get_value();
} else {
attribute_table.custom_options = [];
}
// skip values which don't belong to new type. Bug #2617
attribute_table.skip_unmatched = skip_unmatched || skip_unmatched_org;
attribute_field.reset();
// force value_change to update dirty status if some unmatched values were skipped
attribute_table.value_changed.notify([], attribute_table);
attribute_table.skip_unmatched = skip_unmatched_org;
};
that.update_attrs = function() {
var type_select = that.permission_target.widgets.get_widget('type');
var type = type_select.save()[0];
that.set_attrs_type(type, false);
};
that.post_create = function() {
that.select_target(aci.default_target);
};
that.post_load = function(data) {
var displayed_target = 'general';
var permtype = data.result.result.ipapermissiontype;
that.managed = permtype && permtype.indexOf("MANAGED") > -1;
that.system = permtype && permtype.indexOf("SYSTEM") > -1 && permtype.length === 1;
for (var target in that.target_mapping) {
var property = that.target_mapping[target].property;
if (property && data.result.result[property]) {
displayed_target = target;
} else {
that.set_target_visible(target, false);
}
}
if (displayed_target) {
that.permission_target.target = displayed_target;
that.set_target_visible(displayed_target, true);
}
};
that.select_target = function(target) {
that.set_target_visible(that.permission_target.target, false);
that.permission_target.target = target;
that.set_target_visible(that.permission_target.target, true);
};
that.set_target_visible = function(target, visible) {
var target_info = that.target_mapping[target];
for (var i=0,l=target_info.fields.length; i<l; i++) {
var info = target_info.fields[i];
that.set_target_row_visible(info, visible);
}
if (visible && target_info.action) target_info.action();
};
that.set_target_row_visible = function(target_info, visible) {
var widget = that.permission_target.widgets.get_widget(target_info.name);
var field = that.container.fields.get_field(target_info.name);
that.permission_target.set_row_visible(target_info.name, visible);
field.set_enabled(visible);
field.set_required(visible && target_info.required);
widget.set_visible(visible);
};
that.target_mapping = {
general: {
fields: [
{
name: 'extratargetfilter'
},
{
name: 'ipapermlocation',
required: true
},
{
name: 'ipapermtarget'
},
{
name: 'type'
},
{
name: 'memberof'
},
{
name: 'attrs_multi'
}
]
},
type: {
property: 'type',
fields: [
{
name: 'extratargetfilter'
},
{
name: 'memberof'
},
{
name: 'type'
},
{
name: 'attrs'
},
{
name: 'ipapermtarget'
}
],
action: function() {
that.update_attrs();
}
}
};
return that;
};
/**
* Facet policy which shows and hides managed section based on presence
* "MANAGED" in ippapermissiontype attribute
* @class aci.permission_managed_policy
* @extends IPA.facet_policy
*/
aci.permission_managed_policy = function (spec) {
var that = IPA.facet_policy();
that.post_load = function(data) {
var result = data.result.result;
var permtype = result.ipapermissiontype;
var managed = permtype && permtype.indexOf("MANAGED") > -1;
var system = permtype && permtype.indexOf("SYSTEM") > -1 && permtype.length === 1;
var m_section = that.container.widgets.get_widget("managed");
m_section.set_visible(managed);
var fields = that.container.fields.get_fields();
for (var i=0, l=fields.length; i<l; i++) {
var field = fields[i];
if (field.read_only) continue;
var managed_f = aci.managed_fields.indexOf(field.name) > -1;
field.set_writable(!system && !(managed_f && managed) && field.writable);
}
// Bind rule type cannot be changed if permission is in a privilege
var privileges = result.member_privilege;
if (privileges && privileges.length > 0) {
var f = that.container.fields.get_field('ipapermbindruletype');
f.set_writable(false);
}
};
return that;
};
/**
* Permission entity spec
* @member aci
*/
aci.permission_entity_spec = make_permission_spec();
/**
* Privilege entity spec
* @member aci
*/
aci.privilege_entity_spec = make_privilege_spec();
/**
* Role entity spec
* @member aci
*/
aci.role_entity_spec = make_role_spec();
/**
* Self-service entity spec
* @member aci
*/
aci.selfservice_entity_spec = make_selfservice_spec();
/**
* Delegation entity spec
* @member aci
*/
aci.delegation_entity_spec = make_delegation_spec();
/**
* Register entities, widgets and fields to global registers.
* @member aci
*/
aci.register = function() {
var e = reg.entity;
var w = reg.widget;
var f = reg.field;
e.register({ type: 'permission', spec: aci.permission_entity_spec });
e.register({ type: 'privilege', spec: aci.privilege_entity_spec });
e.register({ type: 'role', spec: aci.role_entity_spec });
e.register({ type: 'selfservice', spec: aci.selfservice_entity_spec });
e.register({ type: 'delegation', spec: aci.delegation_entity_spec });
w.register('attributes', aci.attributes_widget);
f.register('attributes', IPA.field);
w.register('rights', aci.rights_widget);
f.register('rights', IPA.field);
w.register('permission_target', aci.permission_target_widget);
};
phases.on('registration', aci.register);
return aci;
});

View File

@@ -0,0 +1,270 @@
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
* Endi Sukma Dewata <edewata@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['./ipa', './jquery', './navigation', './rpc', './text', './field', './widget', './dialog'],
function(IPA, $, navigation, rpc, text, field_mod, widget_mod) {
/**
* Entity adder dialog
* @class
* @extends IPA.dialog
* @mixins IPA.confirm_mixin
*/
IPA.entity_adder_dialog = function(spec) {
spec = spec || {};
spec.name = spec.name || 'entity_adder_dialog';
var that = IPA.dialog(spec);
that.on_cancel = that.close;
IPA.confirm_mixin().apply(that);
/** @property {string} method="add" API method for add command */
that.method = spec.method || 'add';
/** @property {Function} on_error Custom add error handler */
that.on_error = spec.on_error ;
/** @property {boolean} retry=true Allow retry on error (same as in rpc.command)*/
that.retry = typeof spec.retry !== 'undefined' ? spec.retry : true;
/**
* Add command
* @property {rpc.command}
* @protected
*/
that.command = null;
/** @property {IPA.observer} added Added event */
that.added = IPA.observer();
/** @property {string} subject Name of added subject (usually entity label) */
that.subject = spec.subject || that.entity.metadata.label_singular;
/**
* Pkeys of containing entities to use in add command when adding nested entity
* @property {string[]}
*/
that.pkey_prefix = spec.pkey_prefix || [];
/**
* Custom logic for navigation to edit page in case of 'Add and Edit'
* @property {Function}
* @param {entity.entity} entity
* @param {Object} result
*/
that.show_edit_page = spec.show_edit_page || show_edit_page;
var init = function() {
that.create_button({
name: 'add',
label: '@i18n:buttons.add',
click: function() {
that.on_add();
}
});
that.create_button({
name: 'add_and_add_another',
label: '@i18n:buttons.add_and_add_another',
click: function() {
that.hide_message();
that.add(
function(data, text_status, xhr) {
that.added.notify([data, 'add_and_add_another'], that);
that.show_message(that.get_success_message(data), 'success');
that.reset();
that.focus_first_element();
},
that.on_error);
}
});
that.create_button({
name: 'add_and_edit',
label: '@i18n:buttons.add_and_edit',
click: function() {
that.hide_message();
that.add(
function(data, text_status, xhr) {
that.added.notify([data, 'add_and_edit'], that);
that.close();
var result = data.result.result;
that.show_edit_page(that.entity, result);
that.notify_success(data);
},
that.on_error);
}
});
that.create_button({
name: 'cancel',
label: '@i18n:buttons.cancel',
click: function() {
that.hide_message();
that.close();
}
});
};
/**
* Invokes simple add
* @protected
*/
that.on_add = function() {
that.hide_message();
that.add(
function(data, text_status, xhr) {
that.added.notify([data, 'add'], that);
that.close();
that.notify_success(data);
},
that.on_error);
};
/**
* Confirm handler
* @protected
*/
that.on_confirm = function() {
that.on_add();
};
/**
* Get success notification message text
* @protected
* @param {Object} data Add command result
*/
that.get_success_message = function(data) {
var message = text.get('@i18n:dialogs.add_confirmation');
return message.replace('${entity}', that.subject);
};
/**
* Show success notification
* @protected
* @param {Object} data Add command result
*/
that.notify_success = function(data) {
IPA.notify_success(that.get_success_message(data));
};
function show_edit_page(entity,result) {
var pkey_name = entity.metadata.primary_key;
var pkey = result[pkey_name];
if (!(pkey instanceof Array)) {
pkey = [pkey];
}
rpc.extract_objects(pkey);
var pkeys = that.pkey_prefix.slice(0);
pkeys.push(pkey[0]);
navigation.show_entity(that.entity.name, 'default', pkeys);
}
/**
* Create add command
* @protected
* @param {Object} record Saved data
*/
that.create_add_command = function(record) {
var pkey_name = that.entity.metadata.primary_key;
var command = rpc.command({
entity: that.entity.name,
method: that.method,
retry: that.retry
});
command.add_args(that.pkey_prefix.slice(0));
var fields = that.fields.get_fields();
for (var j=0; j<fields.length; j++) {
var field = fields[j];
var values = record[field.param];
if (!values || values.length === 0 || !field.enabled) continue;
if (field.flags.indexOf('no_command') > -1) continue;
if (field.param === pkey_name) {
command.add_arg(values[0]);
} else if (values.length === 1) {
command.set_option(field.param, values[0]);
} else {
command.set_option(field.param, values);
}
}
return command;
};
/**
* Execute add command
* @param {Function} on_success
* @param {Function} on_error
*/
that.add = function(on_success, on_error) {
if (!that.validate()) {
widget_mod.focus_invalid(that);
return;
}
var record = {};
that.save(record);
that.command = that.create_add_command(record);
that.command.on_success = on_success;
that.command.on_error = on_error;
that.command.execute();
};
/** @inheritDoc */
that.create_content = function() {
that.dialog_create_content();
var div = $('<div/>', {
}).appendTo(that.container);
$('<span/>', {
'class': 'required-indicator',
text: IPA.required_indicator
}).appendTo(div);
div.append(' ');
$('<span/>', {
text: text.get('@i18n:widget.validation.required')
}).appendTo(div);
};
// methods that should be invoked by subclasses
that.entity_adder_dialog_create_content = that.create_content;
that.entity_adder_dialog_create_add_command = that.create_add_command;
that.entity_adder_dialog_get_success_message = that.get_success_message;
init();
return that;
};
return IPA.entity_adder_dialog;
});

View File

@@ -0,0 +1,63 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
// core
'./app_container',
'./plugins/sync_otp',
'./plugins/login',
'./plugins/login_process',
'./plugins/api_browser',
// entities
'./aci',
'./automember',
'./automount',
'./plugins/ca',
'./plugins/caacl',
'./plugins/certprofile',
'./plugins/certmap',
'./plugins/certmapmatch',
'./dns',
'./group',
'./hbac',
'./hbactest',
'./hostgroup',
'./host',
'./idrange',
'./idviews',
'./netgroup',
'./otptoken',
'./policy',
'./radiusproxy',
'./realmdomains',
'./rule',
'./selinux',
'./serverconfig',
'./service',
'./stageuser',
'./sudo',
'./trust',
'./topology',
'./user',
'./vault',
'dojo/domReady!'
],function(app_container) {
return app_container;
});

View File

@@ -0,0 +1,163 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/lang',
'dojo/Deferred',
'dojo/on',
'dojo/when',
'./plugin_loader',
'./phases',
'./reg',
'./Application_controller',
'exports'
],function(lang, Deferred, on, when, plugin_loader, phases, reg, Application_controller, app) {
/**
* Application wrapper
*
* Prepares application controller and registers phases.
*
* @class app
* @singleton
*/
lang.mixin(app, {
/**
* Application instance
*/
app: null,
/**
* Application class
*/
App_class: Application_controller,
/**
* Phases registration
*/
register_phases: function() {
phases.on('init', function() {
var app = this.app = new this.App_class();
app.init();
return app;
}.bind(this));
phases.on('init', function() {
var deferred = new Deferred();
function reject(item) {
var msg = "Web UI requires " + item + " enabled. " +
"Possible cause: too strict browser " +
"configuration.";
deferred.reject({ message: msg });
return deferred.promise;
}
function testStorage(storage) {
try {
if (!window[storage]) return false;
} catch(e) {
return false;
}
return true;
}
if (!window.navigator.cookieEnabled) return reject('cookies');
if (!testStorage('sessionStorage')) return reject('sessionStorage');
if (!testStorage('localStorage')) return reject('localStorage');
if (window.sessionStorage.getItem('logout')) {
window.sessionStorage.removeItem('logout');
var login_facet = reg.facet.get('login');
this.app.show_facet(login_facet);
on.once(login_facet, "logged_in", function() {
deferred.resolve();
});
} else {
deferred.resolve();
}
return deferred.promise;
}.bind(this));
phases.on('metadata', function() {
var deferred = new Deferred();
this.app.get_configuration(function(success) {
deferred.resolve(success);
}, function(error) {
deferred.reject(error);
});
return deferred.promise;
}.bind(this));
phases.on('profile', function() {
this.app.choose_profile();
}.bind(this));
phases.on('runtime', function() {
return this.app.start_runtime();
}.bind(this));
phases.on('shutdown', function() {
return this.app.start_logout();
}.bind(this));
},
simple_mode_phases: function() {
phases.on('init', function() {
var app = this.app = new this.App_class();
app.init();
return app;
}.bind(this));
phases.on('runtime', function() {
var d = new Deferred();
var facet = reg.facet.get(this.target_facet);
if (!facet) {
window.console.error('Target facet not found: '+this.target_facet);
} else {
this.app.show_facet(facet);
}
return d.promise;
}.bind(this));
},
run: function() {
when(plugin_loader.load_plugins(), function() {
this.register_phases();
phases.controller.run();
}.bind(this));
},
run_simple: function(facet) {
this.target_facet = facet;
when(plugin_loader.load_plugins(), function() {
this.simple_mode_phases();
phases.controller.run();
}.bind(this));
}
});
return app;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,252 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2014 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/declare',
'dojo/_base/lang',
'dojo/Deferred',
'dojo/Evented',
'dojo/Stateful',
'dojo/topic',
'dojo/when'
],
function(declare, lang, Deferred, Evented, Stateful, topic, when) {
/**
* Authentication module
* @class auth
* @singleton
*/
var auth = {
/**
* Current authentication state
* @property {auth.Auth}
*/
current: null
};
/**
* Authentication interface and state.
*
* Can be used for checking whether user is authenticated, by what method or
* what methods can be used for authentication. Actual authentication is
* done by separate object - authentication provider.
*
* Communication with authentication providers is done through global messages
* (`dojo/topic`).
*
* Some component can initiate the authentication process by calling:
*
* var auth_promise = auth.current.authenticate();
*
* `auth_promise` is a promise which is resolve on auth success and rejected
* on auth failure.
*
* Logout works in similar fashion:
*
* var logout_promise = auth.current.logout();
*
* The communication with authentication providers works as follows:
*
* 1. `auth.current.authenticate();` publishes `authenticate` topic
* 2. provider starts the authentication process
* 3. if it finishes with a success provider publishes `auth-successful`, if not
* it publishes `auth-failed`
* 4. the promise is resolved or rejected
*
* Logout works in similar fashion, only the topic names are `log-out`,
* `logout-successful` and `logout-failed`.
*
* New `authenticate` or `log-out` topics are not published if there is
* already authentication or logout in progress. The promises from subsequent
* `authenticate()` or `logout()` calls are resolved as expected.
*
* `login`, `principal`, `whoami`, `fullname` properties are supposed to be
* set by authentication providers.
*
* @class
*/
auth.Auth = declare([Stateful, Evented], {
/**
* Raw User information
*
* @property {Object}
*/
whoami: {},
/**
* User is authenticated
*
* Use `set_authenticated(state, method)` for setting it.
*
* @property {boolean}
* @readonly
*/
authenticated: false,
/**
* Method used for authentication
* @property {string}
*/
authenticated_by: "",
/**
* Enabled auth methods
* @property {string[]}
*/
auth_methods: ['kerberos', 'password', 'certificate'],
/**
* Authenticated user's Kerberos principal
* @property {string}
*/
principal: "",
/**
* Authenticated user's login
* @property {string}
*/
login: "",
/**
* Authenticated user's fullname
* @property {string}
*/
fullname: "",
/**
* Authentication is in progress
* @property {boolean}
*/
authenticating: false,
/**
* Logging out is in progress
* @property {boolean}
*/
logging_out: false,
/**
* Indicates whether user was previously authenticated
* @property {boolean}
*/
expired: false,
/**
* Update authenticated state
* @param {boolean} state User is authenticated
* @param {string} method used for authentication
*/
set_authenticated: function(state, method) {
if (this.authenticated && !state) {
this.set('expired', true);
}
this.set('authenticated', state);
this.set('authenticated_by', method);
if (this.authenticated) {
this.set('expired', false);
}
},
/**
* Initiate authentication process (if not already initiated)
*
* Returns promise which is fulfilled when user is authenticated. It's
* rejected when authentication is canceled.
* @returns {Promise}
*/
authenticate: function() {
var authenticated = new Deferred();
var ok_handler = topic.subscribe('auth-successful', function(info) {
authenticated.resolve(true);
ok_handler.remove();
fail_handler.remove();
});
var fail_handler = topic.subscribe('auth-failed', function(info) {
authenticated.reject();
ok_handler.remove();
fail_handler.remove();
});
if (!this.authenticating) {
topic.publish('authenticate', this);
}
return authenticated.promise;
},
/**
* Initiate logout process (if not already initiated)
*
* Returns promise which is fulfilled when user is logged-out. It's
* rejected when logout failed.
* @returns {Promise}
*/
logout: function() {
var loggedout = new Deferred();
var ok_handler = topic.subscribe('logout-successful', function(info) {
loggedout.resolve(true);
ok_handler.remove();
fail_handler.remove();
});
var fail_handler = topic.subscribe('logout-failed', function(info) {
loggedout.reject();
ok_handler.remove();
fail_handler.remove();
});
if (!this.logging_out) {
topic.publish('log-out', this);
}
return loggedout.promise;
},
/**
* Initializes instance
*
* @private
*/
postscript: function() {
var self = this;
var auth_true = function() {
self.set('authenticating', true);
};
var auth_false = function() {
self.set('authenticating', false);
};
var out_true = function() {
self.set('logging_out', true);
};
var out_false = function() {
self.set('logging_out', false);
};
topic.subscribe('auth-successful', auth_false);
topic.subscribe('auth-failed', auth_false);
topic.subscribe('authenticate', auth_true);
topic.subscribe('logout-successful', out_true);
topic.subscribe('logout-failed', out_true);
topic.subscribe('log-out', out_false);
}
});
auth.current = new auth.Auth();
return auth;
});

View File

@@ -0,0 +1,781 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/declare',
'./field',
'./metadata',
'./ipa',
'./jquery',
'./navigation',
'./phases',
'./reg',
'./rpc',
'./text',
'./details',
'./search',
'./association',
'./entity'],
function(declare, field_mod, metadata_provider, IPA, $, navigation,
phases, reg, rpc, text) {
var exp = IPA.automember = {};
var make_spec = function() {
return {
name: 'automember',
policies:[
{
$factory: IPA.facet_update_policy,
source_facet: 'usergrouprule',
dest_facet: 'searchgroup'
},
{
$factory: IPA.facet_update_policy,
source_facet: 'hostgrouprule',
dest_facet: 'searchhostgroup'
}
],
facets: [
{
$factory: IPA.automember.rule_search_facet,
$type: 'search',
name: 'searchgroup',
group_type: 'group',
label: '@i18n:objects.automember.usergrouprules',
details_facet: 'usergrouprule',
pagination: false,
columns: [
'cn',
'description'
]
},
{
$factory: IPA.automember.rule_search_facet,
$type: 'search',
name: 'searchhostgroup',
group_type: 'hostgroup',
label: '@i18n:objects.automember.hostgrouprules',
details_facet: 'hostgrouprule',
pagination: false,
columns: [
'cn',
'description'
]
},
{
$factory: IPA.automember.rule_details_facet,
$type: 'details',
name: 'usergrouprule',
group_type: 'group',
label: '@i18n:objects.automember.usergrouprule',
disable_facet_tabs: true,
check_rights: false,
redirect_info: { facet: 'searchgroup' }
},
{
$factory: IPA.automember.rule_details_facet,
$type: 'details',
name: 'hostgrouprule',
group_type: 'hostgroup',
label: '@i18n:objects.automember.hostgrouprule',
disable_facet_tabs: true,
check_rights: false,
redirect_info: { facet: 'searchhostgroup' }
}
],
adder_dialog: {
$factory: IPA.automember.rule_adder_dialog,
title: '@i18n:objects.automember.add_rule',
fields: [
{
$type: 'entity_select',
name: 'cn',
other_entity: 'group',
other_field: 'cn'
}
],
height: '300'
},
deleter_dialog: {
$factory: IPA.automember.rule_deleter_dialog
}
};};
exp.metadata_extension_pre_op = function(spec, context) {
//HACK: Automember takes_params is missing a cn attribute. This hack
//copies cn from mod command. Also it is set as pkey.
var metadata = metadata_provider.source;
var pkey_attr = metadata.commands.automember_mod.takes_args[0];
pkey_attr.primary_key = true;
metadata.objects.automember.takes_params.push(pkey_attr);
metadata.objects.automember.primary_key = pkey_attr.name;
return spec;
};
IPA.automember.rule_search_facet = function(spec) {
spec = spec || {};
var that = IPA.search_facet(spec);
that.group_type = spec.group_type;
var init = function() {
that.default_group_widget = IPA.automember.default_group_widget({
entity: that.entity,
group_type: that.group_type
});
};
that.refresh = function() {
that.search_facet_refresh();
that.default_group_widget.refresh();
};
that.get_records_command_name = function() {
return that.managed_entity.name + that.group_type+'_get_records';
};
that.get_search_command_name = function() {
var name = that.managed_entity.name + that.group_type + '_find';
if (that.pagination && !that.search_all_entries) {
name += '_pkeys';
}
return name;
};
that.create_get_records_command = function(records, pkeys, on_success, on_error) {
var batch = that.table_facet_create_get_records_command(records, pkeys,
on_success, on_error);
for (var i=0; i<batch.commands.length; i++) {
var command = batch.commands[i];
command.set_option('type', that.group_type);
}
return batch;
};
that.create_refresh_command = function() {
var command = that.search_facet_create_refresh_command();
command.set_option('type', that.group_type);
return command;
};
that.create_content = function(container) {
var header = $('<div/>', {
'class': 'automember-header'
}).appendTo(container);
var content = $('<div/>', {
'class': 'automember-content'
}).appendTo(container);
that.default_group_widget.create(header);
that.table.create(content);
};
that.show_add_dialog = function() {
var dialog = that.managed_entity.get_dialog('add');
if (!that.adder_dialog) {
that.adder_dialog = dialog;
dialog.added.attach(function() {
that.refresh();
});
}
dialog.pkey_prefix = that.managed_entity_pkey_prefix();
dialog.group_type = that.group_type;
dialog.open();
};
that.create_remove_dialog = function() {
var dialog = that.search_facet_create_remove_dialog();
dialog.group_type = that.group_type;
return dialog;
};
init();
return that;
};
IPA.automember.rule_details_facet = function(spec) {
spec = spec || {};
spec.fields = [
{
name: 'cn',
widget: 'general.cn'
},
{
$type: 'textarea',
name: 'description',
widget: 'general.description'
},
{
$type: 'automember_condition',
name: 'automemberinclusiveregex',
widget: 'inclusive.automemberinclusiveregex'
},
{
$type: 'automember_condition',
name: 'automemberexclusiveregex',
widget: 'exclusive.automemberexclusiveregex'
}
];
spec.widgets = [
{
$type: 'details_section',
name: 'general',
label: '@i18n:details.general',
widgets: [
{
name: 'cn'
},
{
$type: 'textarea',
name: 'description'
}
]
},
{
$factory: IPA.section,
name: 'inclusive',
label: '@i18n:objects.automember.inclusive',
widgets: [
{
$type: 'automember_condition',
name: 'automemberinclusiveregex',
group_type: spec.group_type,
add_command: 'add_condition',
remove_command: 'remove_condition',
adder_dialog: {
title: '@i18n:objects.automember.add_condition',
fields: [
{
name: 'key',
$type: 'select',
options: IPA.automember.get_condition_attributes(spec.group_type),
label: '@i18n:objects.automember.attribute'
},
{
name: 'automemberinclusiveregex',
label: '@i18n:objects.automember.expression',
required: true
}
]
}
}
]
},
{
$factory: IPA.section,
name: 'exclusive',
label: '@i18n:objects.automember.exclusive',
widgets: [
{
$type: 'automember_condition',
name: 'automemberexclusiveregex',
group_type: spec.group_type,
add_command: 'add_condition',
remove_command: 'remove_condition',
adder_dialog: {
title: '@i18n:objects.automember.add_condition',
fields: [
{
name: 'key',
$type: 'select',
options: IPA.automember.get_condition_attributes(spec.group_type),
label: '@i18n:objects.automember.attribute'
},
{
name: 'automemberexclusiveregex',
label: '@i18n:objects.automember.expression',
required: true
}
]
}
}
]
}
];
var that = IPA.details_facet(spec);
that.group_type = spec.group_type;
that.get_refresh_command_name = function() {
return that.entity.name+that.group_type+'_show';
};
that.create_refresh_command = function() {
var command = that.details_facet_create_refresh_command();
command.set_option('type', that.group_type);
return command;
};
that.create_update_command = function() {
var command = that.details_facet_create_update_command();
command.set_option('type', that.group_type);
return command;
};
return that;
};
IPA.automember.rule_adder_dialog = function(spec) {
spec = spec || {};
var that = IPA.entity_adder_dialog(spec);
that.group_type = spec.group_type || '';
that.show_edit_page = function (entity,result) {
var pkey_name = entity.metadata.primary_key;
var pkey = result[pkey_name];
if (pkey instanceof Array) {
pkey = pkey[0];
}
var facetname = that.group_type === 'group' ? 'usergrouprule' :
'hostgrouprule';
navigation.show_entity(that.entity.name, facetname, [pkey]);
};
that.reset = function() {
var field = that.fields.get_field('cn');
field.widget.other_entity = IPA.get_entity(that.group_type);
that.dialog_reset();
};
that.create_add_command = function(record) {
var command = that.entity_adder_dialog_create_add_command(record);
command.name = that.entity.name+that.group_type+'_show';
command.set_option('type', that.group_type);
return command;
};
return that;
};
IPA.automember.rule_deleter_dialog = function(spec) {
spec = spec || {};
var that = IPA.search_deleter_dialog(spec);
that.group_type = spec.group_type || '';
that.create_command = function() {
var batch = that.search_deleter_dialog_create_command();
for (var i=0; i<batch.commands.length; i++) {
var command = batch.commands[i];
command.set_option('type', that.group_type);
}
return batch;
};
return that;
};
IPA.automember.get_condition_attributes = function(type) {
var options = [];
if (type === 'group') {
options = metadata_provider.get('@mo:user.aciattrs');
} else if (type === 'hostgroup') {
options = metadata_provider.get('@mo:host.aciattrs');
}
var list_options = IPA.create_options(options);
return list_options;
};
IPA.automember.parse_condition_regex = function(regex) {
var delimeter_index = regex.indexOf('=');
var condition = {
condition: regex,
attribute: regex.substring(0, delimeter_index),
expression: regex.substring(delimeter_index+1)
};
return condition;
};
IPA.automember.condition_field = function(spec) {
spec = spec || {};
spec.adapter = spec.adapter || IPA.automember.condition_adapter;
var that = IPA.field(spec);
return that;
};
IPA.automember.condition_adapter = declare([field_mod.Adapter], {
load: function(data) {
var regexes = this.inherited(arguments);
var values = [];
if (regexes) {
for (var i=0, j=0; i<regexes.length; i++) {
if (regexes[i] === '') continue;
var condition = IPA.automember.parse_condition_regex(regexes[i]);
values.push(condition);
}
}
return values;
}
});
IPA.automember.condition_widget = function(spec) {
spec = spec || {};
spec.footer = spec.footer === undefined ? false : spec.footer;
spec.columns = $.merge(spec.columns || [], [
{
name: 'attribute',
label: '@i18n:objects.automember.attribute'
},
{
name: 'expression',
label: '@i18n:objects.automember.expression'
}
]);
spec.value_attribute = 'condition';
var that = IPA.attribute_table_widget(spec);
that.group_type = spec.group_type;
that.get_additional_options = function() {
return [
{
name: 'type',
value: that.group_type
}
];
};
that.on_add = function(data) {
if (data.result.completed === 0) {
that.refresh_facet();
} else {
that.reload_facet(data);
}
};
that.on_remove = function(data) {
var results = data.result.results;
var i = results.length - 1;
while (i >= 0) {
if (results[i].completed === 1){
that.reload_facet({ error: results[i].error, id: null,
result: results[i] });
return;
}
i--;
}
that.refresh_facet();
};
that.create_remove_command = function(values, on_success, on_error) {
var batch = rpc.batch_command({
name: 'automember_remove_condition',
on_success: on_success,
on_error: on_error
});
var pkeys = that.get_pkeys();
for (var i=0; i<values.length; i++) {
var condition = IPA.automember.parse_condition_regex(values[i]);
var command = that.attribute_table_create_remove_command([]);
command.set_option('key', condition.attribute);
command.set_option(that.attribute_name, condition.expression);
batch.add_command(command);
}
return batch;
};
return that;
};
IPA.automember.default_group_widget = function(spec) {
spec = spec || {};
var that = IPA.widget(spec);
that.group_type = spec.group_type;
that.group = '';
var init = function() {
that.group_select = IPA.entity_select_widget({
name: 'automemberdefaultgroup',
other_entity: that.group_type,
other_field: 'cn',
show_undo: false
});
that.group_select.value_changed.attach(that.group_changed);
};
that.get_group = function() {
var group = that.group_select.save();
group = group.length === 0 ? '' : group[0];
return group;
};
that.set_group = function(group) {
if (group === that.group) return;
that.group = group;
that.group_select.update([group]);
};
that.group_changed = function() {
var group = that.get_group();
if (group === that.group) return;
if (group === '') {
that.remove_default_group();
} else {
that.set_default_group(group);
}
};
that.load = function(data) {
var group = data.result.result.automemberdefaultgroup;
if (group) group = group[0];
if (!group || group.indexOf('cn=') === -1) {
group = '';
} else {
//extract from dn
var i1 = group.indexOf('=');
var i2 = group.indexOf(',');
if (i1 > -1 && i2 > -1) {
group = group.substring(i1 + 1,i2);
}
}
that.update(group);
that.set_visible(true);
};
that.update = function(group) {
group = group || '';
that.set_group(group);
};
that.create_command = function(method) {
method = 'default_group_' + method;
var command_name = that.entity.name + that.group_type + '_' + method;
var command = rpc.command({
name: command_name,
entity: that.entity.name,
method: method,
options: {
type: that.group_type
}
});
return command;
};
that.refresh = function() {
var command = that.create_command('show');
command.retry = false;
command.on_success = that.load;
command.on_error = function() {
that.set_visible(false);
};
command.execute();
};
that.remove_default_group = function() {
var command = that.create_command('remove');
command.on_success = function() {
that.update('');
};
command.on_error = that.refresh;
command.execute();
};
that.set_default_group = function(group) {
var command = that.create_command('set');
command.on_success = that.load;
command.on_error = that.refresh;
command.set_option('automemberdefaultgroup', group);
command.execute();
};
that.create = function(container) {
var title = that.get_title();
that.container = container;
that.header = $('<div/>', {
'class': 'automember-header-label',
name: 'header',
text: title,
title: title
}).appendTo(container);
that.group_select_node = $('<div/>', { 'class': 'automember-header-control' });
that.group_select.create(that.group_select_node);
that.group_select_node.appendTo(container);
that.group_select.update([]); // preload groups
that.set_visible(false);
};
that.get_title = function() {
if (that.group_type === 'group') {
return text.get('@i18n:objects.automember.default_user_group');
} else {
return text.get('@i18n:objects.automember.default_host_group');
}
};
init();
return that;
};
IPA.automember.rebuild_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'automember_rebuild';
spec.label = spec.label || '@i18n:actions.automember_rebuild';
spec.needs_confirm = spec.needs_confirm !== undefined ? spec.needs_confirm : true;
spec.confirm_msg = spec.confirm_msg || '@i18n:actions.automember_rebuild_confirm';
var that = IPA.action(spec);
that.execute_action = function(facet) {
var entity = facet.entity.name;
if (facet.name == 'search') {
var entries = facet.get_selected_values();
} else {
entries = facet.get_pkeys();
}
var options = {};
if (entries.length > 0) {
options[entity + 's'] = entries;
} else if (entity == 'user') {
options['type'] = 'group';
} else {
options['type'] = 'hostgroup';
}
var command = rpc.command({
entity: 'automember',
method: 'rebuild',
options: options,
on_success: function() {
IPA.notify_success('@i18n:actions.automember_rebuild_success');
},
on_error: function() {
}
});
command.execute();
};
return that;
};
exp.entity_spec = make_spec();
exp.register = function() {
var e = reg.entity;
var w = reg.widget;
var f = reg.field;
var a = reg.action;
e.register({
type: 'automember',
spec: exp.entity_spec,
pre_ops: [ exp.metadata_extension_pre_op ]
});
w.register('automember_condition', IPA.automember.condition_widget);
f.register('automember_condition', IPA.automember.condition_field);
a.register('automember_rebuild', exp.rebuild_action);
};
phases.on('registration', exp.register);
return exp;
});

View File

@@ -0,0 +1,376 @@
/* Authors:
* Adam Young <ayoung@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./navigation',
'./phases',
'./reg',
'./details',
'./search',
'./association',
'./entity'],
function(IPA, $, navigation, phases, reg) {
var exp = IPA.automount = {};
var make_location_spec = function() {
return {
name: 'automountlocation',
facet_groups: [ 'automountmap', 'settings' ],
facets: [
{
$type: 'search',
title: '@mo:automountlocation.label',
columns:['cn']
},
{
$type: 'nested_search',
facet_group: 'automountmap',
nested_entity: 'automountmap',
label: '@mo:automountmap.label',
tab_label: '@mo:automountmap.label',
name: 'maps',
columns: [ 'automountmapname' ]
},
{
$type: 'details',
sections:[
{
name: 'identity',
label: '@i18n:details.identity',
fields: [ 'cn' ]
}
]
}
],
adder_dialog: {
fields: [ 'cn' ]
}
};};
var make_map_spec = function() {
return {
name: 'automountmap',
containing_entity: 'automountlocation',
facet_groups: [ 'automountkey', 'settings' ],
facets: [
{
$type: 'nested_search',
$factory: IPA.automount.key_search_facet,
facet_group: 'automountkey',
nested_entity: 'automountkey',
search_all_entries: true,
label: '@mo:automountkey.label',
tab_label: '@mo:automountkey.label',
name: 'keys',
columns: [
{
$factory: IPA.automount_key_column,
name: 'automountkey',
label: '@mo-param:automountkey:automountkey:label'
},
'automountinformation'
]
},
{
$type: 'details',
sections: [
{
name: 'identity',
label: '@i18n:details.identity',
fields: [
'automountmapname',
{
$type: 'textarea',
name: 'description'
}
]
}
]
}
],
adder_dialog: {
$factory: IPA.automountmap_adder_dialog,
sections: [
{
name: 'general',
fields: [
{
$type: 'radio',
name: 'method',
flags: ['no_command'],
label: '@i18n:objects.automountmap.map_type',
options: [
{
value: 'add',
label: '@i18n:objects.automountmap.direct'
},
{
value: 'add_indirect',
label: '@i18n:objects.automountmap.indirect'
}
]
},
'automountmapname',
{
$type: 'textarea',
name: 'description'
}
]
},
{
name: 'indirect',
fields: [
{
name: 'key',
label: '@mc-opt:automountmap_add_indirect:key:label'
},
{
name: 'parentmap',
label: '@mc-opt:automountmap_add_indirect:parentmap:label'
}
]
}
]
}
};};
var make_key_spec = function() {
return {
name: 'automountkey',
policies:[
{
$factory: IPA.facet_update_policy,
source_facet: 'details',
dest_entity: 'automountmap',
dest_facet: 'keys'
}
],
containing_entity: 'automountmap',
facets: [
{
$type: 'details',
$factory: IPA.automount.key_details_facet,
sections: [
{
name:'identity',
label: '@i18n:details.identity',
fields: [
{
name: 'automountkey',
read_only: true
},
'automountinformation'
]
}
],
disable_breadcrumb: false
}
],
adder_dialog: {
show_edit_page : function(entity, result){
var key = result.automountkey[0];
var info = result.automountinformation[0];
var pkeys = this.pkey_prefix.slice(0);
pkeys.push(key);
var args = {
info: info,
key: key
};
navigation.show_entity(entity.name, 'details', pkeys, args);
return false;
},
fields:['automountkey','automountinformation']
}
};};
IPA.automount.key_details_facet = function(spec) {
var that = IPA.details_facet(spec);
that.create_update_command = function() {
var command = that.details_facet_create_update_command();
command.args.pop();
var key = that.state.key;
var info = that.state.info;
command.options.newautomountinformation = command.options.automountinformation;
command.options.automountkey = key;
command.options.automountinformation = info;
return command;
};
that.create_refresh_command = function() {
var command = that.details_facet_create_refresh_command();
command.args.pop();
var key = that.state.key;
var info = that.state.info;
command.options.automountkey = key;
command.options.automountinformation = info;
return command;
};
return that;
};
IPA.automount_key_column = function(spec) {
var that = IPA.column(spec);
that.setup = function(container, record) {
container.empty();
var key = record.automountkey;
if (key instanceof Array) key = key[0];
var info = record.automountinformation;
if (info instanceof Array) info = info[0];
$('<a/>', {
href: '#'+key,
text: key,
click: function() {
var pkeys = that.facet.get_pkeys();
pkeys.push(key);
var args = {
info: info,
key: key
};
navigation.show_entity(that.entity.name, 'details', pkeys, args);
return false;
}
}).appendTo(container);
};
return that;
};
IPA.automountmap_adder_dialog = function(spec) {
var that = IPA.entity_adder_dialog(spec);
that.create_content = function() {
that.entity_adder_dialog_create_content();
var method_widget = that.widgets.get_widget('general.method');
var indirect_section = that.widgets.get_widget('indirect');
var key_field = that.fields.get_field('key');
var parentmap_field = that.fields.get_field('parentmap');
var direct_input = $('input[value="add"]', method_widget.container);
direct_input.change(function() {
that.method = 'add';
key_field.set_enabled(false);
parentmap_field.set_enabled(false);
key_field.set_required(false);
indirect_section.set_visible(false);
});
var indirect_input = $('input[value="add_indirect"]', method_widget.container);
indirect_input.change(function() {
that.method = 'add_indirect';
key_field.set_enabled(true);
parentmap_field.set_enabled(true);
key_field.set_required(true);
indirect_section.set_visible(true);
});
direct_input.prop('checked', true);
direct_input.trigger('change');
};
that.reset = function() {
that.dialog_reset();
var method_widget = that.widgets.get_widget('general.method');
var direct_input = $('input[value="add"]', method_widget.container);
direct_input.prop('checked', true);
direct_input.trigger('change');
};
return that;
};
IPA.automount.key_search_facet = function(spec) {
var that = IPA.nested_search_facet(spec);
that.get_selected_values = function() {
var values = [];
var keys = that.table.get_selected_values();
var records = that.table.records;
if (keys.length === 0 || !records) return values;
for (var i=0,l=records.length; i<l; i++) {
var record = records[i];
if (keys.indexOf(record.description[0]) > -1) {
values.push({
automountkey: record.automountkey[0],
automountinformation: record.automountinformation[0]
});
}
}
return values;
};
return that;
};
exp.location_spec = make_location_spec();
exp.map_spec = make_map_spec();
exp.key_spec = make_key_spec();
exp.register = function() {
var e = reg.entity;
e.register({type: 'automountlocation', spec: exp.location_spec});
e.register({type: 'automountmap', spec: exp.map_spec});
e.register({type: 'automountkey', spec: exp.key_spec});
};
phases.on('registration', exp.register);
return exp;
});

View File

@@ -0,0 +1,82 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/array',
'dojo/_base/lang',
'./_base/Builder',
'./_base/Singleton_registry'
], function(declare, array, lang, Builder, Singleton_registry) {
var builder_registry = new Singleton_registry();
builder_registry.builder.ctor = Builder;
/**
* Global builder interface.
*
* Contains a map of builders for a specific object type.
*
* @class builder
* @singleton
*/
var exp = {
/**
* Registry of builders
* @property {_base.Singleton_registry}
*/
builders: builder_registry,
/**
* Get builder for object type
*
* @param {string} object type
*/
get: function(obj_type) {
return this.builders.get(obj_type);
},
/**
* Set builder for object type.
*
* @param {string} object type
* @param {_base.Builder} builder
*/
set: function(obj_type, builder) {
this.builders.set(obj_type, builder);
},
/**
* Build object by builder for given object type.
*
* @param {string} object type. Uses generic builder if empty string.
* @param {string|Object|Function} spec
* @param {Object|null} context
* @param {Object|null} build overrides
*/
build: function(obj_type, spec, context, overrides) {
obj_type = obj_type || 'generic';
var builder = this.builders.get(obj_type);
return builder.build(spec, context, overrides);
}
};
return exp;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,128 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/declare',
'dojo/topic'
],
function(declare, topic) {
/**
* Application configuration
* @class config
* @singleton
*/
var config = declare([], {
/**
* Selector for application container node
*/
app_container: 'body',
/**
* Live server path
*/
url: '/ipa/ui/',
/**
* RPC url
*/
json_url: '/ipa/session/json',
/**
* Kerberos authentication url
*/
krb_login_url: '/ipa/session/login_kerberos',
/**
* Forms based login url
*/
frms_login_url: '/ipa/session/login_password',
//logout_url: '/ipa/session/json',
/**
* Password reset url
*/
reset_psw_url: '/ipa/session/change_password',
/**
* Ajax options for RPC commands
*/
ajax_options: {
type: 'POST',
contentType: 'application/json',
dataType: 'json',
async: true,
processData: false
},
/**
* Hide read-only widgets without value
* @property {boolean}
*/
hide_empty_widgets: false,
/**
* Hide sections without any visible widget
* @property {boolean}
*/
hide_empty_sections: true,
/**
* Number of lines in table on table_facets
* @property {Integer}
*/
table_page_size: 20,
/**
* Genereal setter for config values.
* @param item_name {string}
* @param value
* @param store {Boolean} sets whether the value will be stored into
* local storage
*/
set: function(item_name, value, store) {
if (!item_name) return;
this[item_name] = value;
if (store) {
window.localStorage.setItem(item_name, value);
}
},
/**
* Genereal setter for config values.
* @param item_name {string}
*/
get: function(item_name) {
return this[item_name];
},
constructor: function() {
var user_limit = window.localStorage.getItem('table_page_size');
if (user_limit) this.table_page_size = user_limit;
}
});
return new config();
});

View File

@@ -0,0 +1,27 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./app_container',
'./plugins/sync_otp',
'./plugins/login'
],function(app_container) {
return app_container;
});

View File

@@ -0,0 +1,217 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2014 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/string'
], function(string) {
var templates = {
human: '${YYYY}-${MM}-${DD} ${HH}:${mm}:${ss}Z',
generalized: '${YYYY}${MM}${DD}${HH}${mm}${ss}Z'
};
var dates = [
['YYYY-MM-DD', /^(\d{4})-(\d{2})-(\d{2})$/],
['YYYYMMDD',/^(\d{4})(\d{2})(\d{2})$/]
];
var times = [
['HH:mm:ss', /^(\d\d):(\d\d):(\d\d)$/],
['HH:mm', /^(\d\d):(\d\d)$/]
];
var generalized_regex = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z$/;
var datetime_regex = /^((?:\d{8})|(?:\d{4}-\d{2}-\d{2}))(?:(T| )(\d\d:\d\d(?::\d\d)?)(Z?))?$/;
function parse(value) {
var Y=0, M=0, D=0, H=0, m=0, s=0;
var i, l, dateStr, timeStr, utc;
var dt_match = datetime_regex.exec(value);
var gt_match = generalized_regex.exec(value);
if (dt_match) {
dateStr = dt_match[1];
timeStr = dt_match[3];
utc = dt_match[4] || !timeStr;
// error out if local time not supported
if (!this.allow_local && !utc) return null;
for (i = 0, l = dates.length; i < l; i++) {
var dm = dates[i][1].exec(dateStr);
if (dm) {
Y = dm[1];
M = dm[2];
D = dm[3];
break;
}
}
if (timeStr) {
for (i = 0, l = times.length; i < l; i++) {
var tm = times[i][1].exec(timeStr);
if (tm) {
H = tm[1];
m = tm[2] || 0;
s = tm[3] || 0;
break;
}
}
}
} else if (gt_match) {
Y = gt_match[1];
M = gt_match[2];
D = gt_match[3];
H = gt_match[4];
m = gt_match[5];
s = gt_match[6];
utc = true;
} else {
return null;
}
var date = new Date();
if (utc || !timeStr) {
date.setUTCFullYear(Y, M-1, D);
date.setUTCHours(H, m, s, 0);
} else {
date.setFullYear(Y, M-1, D);
date.setHours(H, m, s, 0);
}
return date;
}
function formatDate(date, format, local) {
var fmt = format || templates.human;
var str;
function pad(value) {
return string.pad(value, 2, '0');
}
if (local) {
str = string.substitute(fmt, {
YYYY: date.getFullYear(),
MM: pad(date.getMonth()+1),
DD: pad(date.getDate()),
HH: pad(date.getHours()),
mm: pad(date.getMinutes()),
ss: pad(date.getSeconds())
});
} else {
str = string.substitute(fmt, {
YYYY: date.getUTCFullYear(),
MM: pad(date.getUTCMonth()+1),
DD: pad(date.getUTCDate()),
HH: pad(date.getUTCHours()),
mm: pad(date.getUTCMinutes()),
ss: pad(date.getUTCSeconds())
});
}
return str;
}
/**
* Utility module to parse strings in ISO 8601-ish format into Date object
* and vice versa
*
* @class datetime
* @singleton
*/
var datetime = {
/**
* Parse string, return date or null on error.
*
* Supported date formats:
*
* - `YYYY-MM-DD`
* - `YYYYMMDD`
*
* Supported time formats:
*
* - `HH:mm:ss`
* - `HH:mm`
*
* Supported formats:
*
* - `$dateT$timeZ`
* - `$date $timeZ`
* - `$date`
* - `YYYYMMDDHHmmssZ`
*
* Where Z indicates UTC date. Parsing of local dates is by default
* disabled. It can be enabled by setting `datetime.allow_local` to
* `true`.
*
* @param {string} value
* @returns {Date|null} parsed date
*/
parse: parse,
/**
* Convert date to string
*
* - `${YYYY}` - year
* - `${MM}` - month
* - `${DD}` - day
* - `${HH}` - hours
* - `${mm}` - minutes
* - `${ss}` - seconds
*
* Default format string: `${YYYY}-${MM}-${DD} ${HH}:${mm}:${ss}`
*
* @param {Date} date
* @param {string} [format] format string
* @param {boolean} [local] use local time
*/
format: formatDate,
/**
* Local time input method support
* @property {boolean}
*/
allow_local: false,
/**
* Convert date value to generalized time string
* @param {Date} date
* @returns {string}
*/
to_generalized_time: function(date) {
return this.format(date, templates.generalized);
},
/**
* Dictionary of common format strings
*
* - `human` - default format string of `format` method
* - `generalized` - generalized time (LDAP) format
*
* @property {Object}
*/
templates: templates
};
return datetime;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
define(['./ipa'], function(IPA) {
//polute global namespace - easy usage in browser console
window.IPA = IPA;
var console = window.console; // avoid jsl error
var tools = window.ipadev = IPA.dev = {
// map of loaded modules
modules: {},
get: function (mid,name) {
/* loads module into ipa dev modules property */
var self = this;
var mid_parts = mid.split('/');
name = name || mid_parts[mid_parts.length-1];
require([mid], function(module) {
self.modules[name] = module;
console.log('Module '+mid+' loaded.');
});
}
};
console.log('Dev tools loaded.');
return tools;
}); //define

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,147 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/lang',
'../builder',
'../ipa',
'../phases',
'../reg',
'../rpc',
'../text',
'../dialog'],
function(lang, builder, IPA, phases, reg, rpc, text, dialogs) {
/**
* Password dialog module
* @class
* @singleton
*/
dialogs.password = {};
var DP = dialogs.password;
/**
* Dialog's pre_ops
*/
dialogs.password.default_fields_pre_op = function(spec) {
var name = spec.password_name || 'password1';
var label = spec.password_label || '@i18n:password.new_password';
var verify_label = spec.verify_label ||'@i18n:password.verify_password';
spec.title = spec.title || '@i18n:password.reset_password';
spec.width = spec.width || 400;
spec.success_message = spec.success_message || '@i18n:password.password_change_complete';
spec.confirm_button_label = spec.confirm_button_label || '@i18n:password.reset_password';
spec.sections = spec.sections || [
{
name: 'general',
fields: [
{
name: name,
label: label,
$type: 'password',
required: true
},
{
name: 'password2',
label: verify_label,
$type: 'password',
required: true,
flags: ['no_command'],
validators: [{
$type: 'same_password',
other_field: name
}]
}
]
}
];
return spec;
};
/**
* Action to open a password dialog
* @class
* @extends facet.action
*/
dialogs.password.action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'password';
spec.label = spec.label || '@i18n:password.reset_password';
var that = IPA.action(spec);
/**
* Dialog spec
* @property {Object}
*/
that.dialog = spec.dialog || {};
/**
* Refresh facet after successful password reset
* @property {boolean} refresh=true
*/
that.refresh = spec.refresh !== undefined ? spec.refresh : true;
/**
* @inheritDoc
*/
that.execute_action = function(facet) {
var ds = lang.clone(that.dialog);
ds.entity = ds.entity || facet.entity;
if (!ds.$type && !ds.$factory && !ds.$ctor) {
ds.$type = 'password';
}
var dialog = builder.build('dialog', ds);
dialog.args = facet.get_pkeys();
dialog.succeeded.attach(function() {
if (that.refresh) facet.refresh();
});
dialog.open();
};
return that;
};
/**
* Register dialog
* @member dialogs.password
*/
dialogs.password.register = function() {
var d = reg.dialog;
var a = reg.action;
d.register({
type: 'password',
factory: dialogs.command_dialog,
pre_ops: [DP.default_fields_pre_op],
post_ops: [dialogs.command_dialog_post_op]
});
a.register('password', DP.action);
};
phases.on('registration', DP.register);
return DP;
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2014 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/lang',
'./jquery',
'./phases',
'./app_container',
'exports'
],function(lang, $, phases, app, extend) {
/**
* Extension interface
*
* This class provides interface for plugins and tries to hide underlying functionality
*
* @class extend
* @singleton
*/
lang.mixin(extend, {
/**
* Adds element to utility section
*
* This method doesn't do any correction. Expended root node type to add is
* by default `<li>`.
*
* Preferred phase: any after `init`
*
* @param {HTMLElement|jQuery} element Element to add to utility section
* @return {HTMLElement} Utility node
*/
add_menu_utility: function(element) {
// Should we check if we are in good stage or atleast report that app doesn't exist yet?
var $utility = $(app.app.app_widget.nav_util_tool_node);
$utility.prepend(element);
return $utility.eq(0);
}
});
return extend;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
//
// Copyright (C) 2015 FreeIPA Contributors see COPYING for license
//
define(['dojo/_base/declare',
'../builder',
'../facet'
],
function(declare, builder, mod_facet) {
/**
* Header Mixin
*
* Extension of facet - actions
*
* @class facets.ActionMixin
*/
var ActionMixin = declare([], {
/**
* State object for actions
* @property {facet.state}
*/
action_state: null,
/**
* Collection of facet actions
* @property {facet.action_holder}
*/
actions: null,
show: function() {
this.inherited(arguments);
this.actions.on_load();
},
/** Constructor */
constructor: function(spec) {
this.action_state = builder.build('', spec.state || {}, {}, { $factory: mod_facet.state });
this.actions = builder.build('', { actions: spec.actions }, {}, { $factory: mod_facet.action_holder } );
this.action_state.init(this);
this.actions.init(this);
}
});
return ActionMixin;
});

View File

@@ -0,0 +1,357 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/lang',
'dojo/Evented',
'dojo/dom-construct',
'dojo/dom-class',
'dojo/on',
'../builder',
'../facet',
'../ipa', // for util functions
'../jquery',
'../text',
'../widgets/ContainerMixin'
],
function(declare, lang, Evented, construct, dom_class,
on, builder, mod_facet, IPA, $, text, ContainerMixin) {
/**
* Base class of Facet
*
* A future replacement/base class for `facet.facet`
*
* @class facets.Facet
* @mixins widgets.ContainerMixin
*/
var Facet = declare([Evented, ContainerMixin], {
/**
* Name of preferred facet container
*
* Leave unset to use default container.
* @property {string}
*/
preferred_container: null,
/**
* Facet name
* @property {string}
*/
name: null,
/**
* Facet label
* @property {string}
*/
label: null,
/**
* Facet title
* @property {string}
*/
title: null,
/**
* Facet tab label
* @property {string}
*/
tab_label: null,
/**
* Facet element's CSS class
* @property {string}
*/
'class': null,
/**
* Class which tells that the facet should be visible
* @property {string}
*/
active_class: 'active',
/**
* dom_node of container
* Suppose to contain dom_node of this and other facets.
* @property {jQuery}
*/
container_node: null,
/**
* dom_node which contains all content of this Facet.
* @property {HTMLElement}
* @readonly
*/
dom_node: null,
/**
* DOM node which serves as container for child widgets
* @property {HTMLElement}
*/
children_node: null,
/**
* Redirection target information.
*
* Can be facet and/or entity name.
* @property {Object}
* @param {string} entity entity name
* @param {string} facet facet name
*/
redirect_info: null,
/**
* Facet requires authenticated user
* @type {Boolean}
*/
requires_auth: true,
/**
* Public state
* @property {facet.FacetState}
* @protected
*/
state: null,
get_full_name: function() {
return this.name;
},
/**
* Checks if two objects has the same properties with equal values.
*
* @param {Object} a
* @param {Object} b
* @return {boolean} `a` and `b` are value-equal
* @protected
*/
state_diff: function(a, b) {
var diff = false;
var checked = {};
var check_diff = function(a, b, skip) {
var same = true;
skip = skip || {};
for (var key in a) {
if (a.hasOwnProperty(key) && !(key in skip)) {
var va = a[key];
var vb = b[key];
if (lang.isArray(va)) {
if (IPA.array_diff(va,vb)) {
same = false;
skip[a] = true;
break;
}
} else {
if (va != vb) {
same = false;
skip[a] = true;
break;
}
}
}
}
return !same;
};
diff = check_diff(a,b, checked);
diff = diff || check_diff(b,a, checked);
return diff;
},
/**
* Reset facet state to supplied
*
* @param {Object} state state to set
*/
reset_state: function(state) {
this.state.reset(state);
},
/**
* Get copy of current state
*
* @return {Object} state
*/
get_state: function() {
return this.state.clone();
},
/**
* Merges state into current and notifies it.
*
* @param {Object} state object to merge into current state
*/
set_state: function(state) {
this.state.set(state);
},
/**
* Handle state set
* @param {Object} old_state
* @param {Object} state
* @protected
*/
on_state_set: function(old_state, state) {
this.on_state_change(state);
},
/**
* Handle state change
* @param {Object} state
* @protected
*/
on_state_change: function(state) {
this._notify_state_change(state);
},
/**
* Fires `facet-state-change` event with given state as event parameter.
*
* @fires facet-state-change
* @protected
* @param {Object} state
*/
_notify_state_change: function(state) {
this.emit('facet-state-change', {
facet: this,
state: state
});
},
/**
* Create facet's HTML representation
* NOTE: may be renamed to render
*/
create: function() {
if (this.dom_node) {
construct.empty(this.dom_node);
} else {
this.dom_node = construct.create('div', {
'class': 'facet',
name: this.name,
'data-name': this.name
});
}
if (this['class']) {
dom_class.add(this.dom_node, this['class']);
}
if (this.container_node) {
construct.place(this.dom_node, this.container_node);
}
this.children_node = this.dom_node;
return this.dom_node;
},
/**
* Render child widgets
*/
render_children: function() {
var widgets = this.get_widgets();
for (var i=0;i<widgets.length; i++) {
var widget = widgets[i];
var modern = typeof widget.render === 'function';
if (modern) {
widget.container_node = this.children_node;
widget.render();
} else {
var container = $('<div/>').appendTo(this.children_node);
widget.create(container);
}
}
},
/**
* Show facet
*
* - mark itself as active facet
*/
show: function() {
if (!this.dom_node) {
this.create();
this.render_children();
} else if (!this.dom_node.parentElement) {
construct.place(this.dom_node, this.container_node);
}
dom_class.add(this.dom_node, 'active-facet');
this.emit('show', { source: this });
},
/**
* Un-mark itself as active facet
*/
hide: function() {
if (this.dom_node.parentElement) {
this.container_node.removeChild(this.dom_node);
}
dom_class.remove(this.dom_node, 'active-facet');
this.emit('hide', { source: this });
},
/**
* Initializes facet
*
* Facet builder should run this method after instantiation.
* @param {Object} spec
*/
init: function(spec) {
this.add_widgets(spec.widgets || []);
},
can_leave: function() {
return true;
},
show_leave_dialog: function(callback) {
window.console.warning('Unimplemented');
},
/** Constructor */
constructor: function(spec) {
this.preferred_container = spec.preferred_container;
this.name = spec.name;
this.label = text.get(spec.label);
this.tab_label = text.get(spec.tab_label || spec.label);
this.title = text.get(spec.title || spec.label);
this['class'] = spec['class'];
this.container_node = spec.container_node;
this.dom_node = spec.dom_node;
this.redirect_info = spec.redirect_info;
if (spec.requires_auth !== undefined) {
this.requires_auth = spec.requires_auth;
}
this.state = new mod_facet.FacetState();
on(this.state, 'set', this.on_state_set.bind(this));
}
});
return Facet;
});

View File

@@ -0,0 +1,260 @@
//
// Copyright (C) 2015 FreeIPA Contributors see COPYING for license
//
define(['dojo/_base/declare',
'dojo/_base/lang',
'dojo/on',
'dojo/dom-construct',
'dojo/dom-class',
'../builder',
'../facet',
'../text',
'../widgets/ActionDropdownWidget'
],
function(declare, lang, on, construct, dom_class,
builder, mod_facet, text, ActionDropdownWidget) {
/**
* Header Mixin
*
* Extension of facet - header with title and facet groups. Requires
* facets.ActionMixin.
*
* @class facets.HeaderMixin
*/
var HeaderMixin = declare([], {
/**
* Facet header
* @property {facet.facet_header}
*/
header: null,
/**
* Facet tabs are not displayed when set.
* @property {boolean}
*/
disable_facet_tabs: false,
/**
* Facet tabs in sidebar
*
* There is and effort (#4625) to move all facet tabs into sidebar but it
* was not user tested, therefore they remain on the old place for the
* time being.
*
* This option should be changed when ^^ is removed.
* @property {boolean}
*/
tabs_in_sidebar: true,
/**
* Array of actions which are displayed in facet header
* @property {Array.<string>}
*/
header_actions: null,
/**
* Facet groups
*
* @property {IPA.facet_group[]}
*/
facet_groups: null,
/**
* Facet group name
* @property {string}
*/
facet_group: null,
/**
* Create facet's HTML representation
* NOTE: may be renamed to render
*/
create: function() {
// this create method is Facet.create extended by header/sidebar logic
if (this.dom_node) {
construct.empty(this.dom_node);
} else {
this.dom_node = construct.create('div', {
'class': 'facet',
name: this.name,
'data-name': this.name
});
}
if (this['class']) {
dom_class.add(this.dom_node, this['class']);
}
if (this.container_node) {
construct.place(this.dom_node, this.container_node);
}
var row = $('<div/>', {
'class': 'row'
}).appendTo(this.dom_node);
var content_cont = row;
this.sidebar_content_el = $('<div/>', {
'class': mod_facet.sidebar_content_width
}).appendTo(row);
content_cont = $('<div/>', {
'class': 'row'
}).appendTo(this.sidebar_content_el);
this.sidebar_el = $('<div/>', {
'class': mod_facet.sidebar_class + mod_facet.sidebar_width
}).appendTo(row);
this.header_container = $('<div/>', {
'class': 'facet-header col-sm-12'
}).appendTo(content_cont);
this.create_header(this.header_container);
this.content = $('<div/>', {
'class': 'facet-content col-sm-12'
}).appendTo(content_cont);
this.children_node = this.content[0];
return this.dom_node;
},
/**
* Create control buttons
*
* @param {jQuery} container
* @protected
*/
create_header: function(container) {
this.header.create(container);
this.controls = $('<div/>', {
'class': 'facet-controls clearfix'
}).appendTo(container);
this.controls_left = $('<div/>', {
'class': 'facet-controls-left'
}).appendTo(this.controls);
this.controls_right = $('<div/>', {
'class': 'facet-controls-right'
}).appendTo(this.controls);
this.create_controls();
},
/**
* Create header controls
*
* - ie control buttons orActionDropDown
*/
create_controls: function() {
this.create_control_buttons(this.controls_left);
this.create_action_dropdown(this.controls_left);
},
/**
* Create control buttons
*
* @param {jQuery} container
* @protected
*/
create_control_buttons: function(container) {
if (this.control_buttons) {
this.control_buttons.create(container);
}
},
/**
* Create action dropdown widget in supplied container
*
* @param {jQuery} container
* @protected
*/
create_action_dropdown: function(container) {
if (this.action_dropdown && this.header_actions && this.header_actions.length > 0) {
var dropdown = this.action_dropdown.render();
container.append(dropdown);
}
},
/**
* Display or hide facet tabs - either in sidebar or facet header
* @param {boolean} visible
*/
set_tabs_visible: function(visible) {
if (this.disable_facet_tabs) return;
if (this.tabs_in_sidebar && this.sidebar_el) {
var a = visible ? mod_facet.sidebar_content_width : mod_facet.sidebar_content_full_width;
var r = visible ? mod_facet.sidebar_content_full_width : mod_facet.sidebar_content_width;
this.sidebar_content_el.removeClass(r);
this.sidebar_content_el.addClass(a);
this.sidebar_el.css('display', visible ? '' : 'none');
}
this.header.set_tabs_visible(visible);
},
/**
* Overrides parent's object(usually facet.Facet) show method. To select a
* tab.
*/
show: function() {
this.inherited(arguments);
this.header.select_tab();
},
/** Constructor */
constructor: function(spec) {
this.facet_groups = builder.build('', spec.facet_groups, {}, {
$factory: mod_facet.facet_group
});
this.facet_group = spec.facet_group;
this.header = builder.build(
'',
spec.header || { init_group_names: true},
{},
{
$pre_ops: [{ facet: this }],
$factory: mod_facet.simple_facet_header
}
);
this.header.init();
this.header_actions = spec.header_actions || [];
var buttons_spec = {
$factory: mod_facet.control_buttons_widget,
name: 'control-buttons',
css_class: 'control-buttons',
buttons: spec.control_buttons
};
this.control_buttons = builder.build(null, buttons_spec);
this.control_buttons.init(this);
this.action_dropdown = builder.build(null, {
$ctor: ActionDropdownWidget,
action_names: this.header_actions,
name: 'facet_actions',
'class': 'dropdown facet-actions',
right_aligned: true,
toggle_text: text.get('@i18n:actions.title') + ' ',
toggle_class: 'btn btn-default',
toggle_icon: 'fa fa-angle-down'
});
this.action_dropdown.init(this);
}
});
return HeaderMixin;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
//
// Dojo builder profile file
//
var profile = (function(){
var js_files = /\.js$/;
return {
resourceTags: {
// all JavaScript files are AMD modules
amd: function(filename, mid) {
return js_files.test(filename);
}
}
};
})();

View File

@@ -0,0 +1,301 @@
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
* Endi Dewata <edewata@redhat.com>
* Adam Young <ayoung@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/on',
'./ipa',
'./jquery',
'./phases',
'./reg',
'./details',
'./search',
'./association',
'./entity'],
function(on, IPA, $, phases, reg) {
var exp = IPA.group = {
search_facet_group: {
name: 'search',
label: '@i18n:objects.group.group_categories',
facets: {
search_group: 'group_search',
search_hostgroup: 'hostgroup_search',
search_netgroup: 'netgroup_search'
}
}
};
var make_spec = function() {
return {
name: 'group',
facets: [
{
$type: 'search',
tab_label: '@i18n:objects.group.user_groups',
facet_groups: [IPA.group.search_facet_group],
tabs_in_sidebar: true,
disable_facet_tabs: false,
columns: [
'cn',
'gidnumber',
'description'
]
},
{
$type: 'details',
sections: [
{
name: 'details',
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
},
{
$type: 'value_map',
name: 'external',
param: 'objectclass',
label: '@i18n:objects.group.type',
default_label: '@i18n:objects.group.nonposix',
value_map: {
ipaexternalgroup: '@i18n:objects.group.external',
posixgroup: '@i18n:objects.group.posix'
}
},
'gidnumber',
{
$type: 'link',
name: 'pwpolicy',
param: 'cn',
label: '@mo:pwpolicy.label_singular',
other_entity: 'pwpolicy',
require_link: true
}
]
}
],
actions: [
'select',
'make_posix',
'make_external',
'delete'
],
header_actions: ['make_posix', 'make_external', 'delete'],
state: {
evaluators: [
IPA.object_class_evaluator
]
}
},
{
$type: 'association',
name: 'member_user',
columns:[
'uid',
'uidnumber',
'mail',
'telephonenumber',
'title'
],
adder_columns:[
{
name: 'uid',
primary_key: true
}
]
},
{
$type: 'association',
name: 'member_group'
},
{
$type: 'attribute',
name: 'member_external',
attribute: 'ipaexternalmember',
tab_label: 'External',
facet_group: 'member',
columns: [
{
name: 'ipaexternalmember',
label: '@mc-opt:group_add_member:ipaexternalmember:label'
}
]
},
{
$type: 'association',
name: 'memberof_group',
associator: IPA.serial_associator
},
{
$type: 'association',
name: 'memberof_netgroup',
associator: IPA.serial_associator
},
{
$type: 'association',
name: 'memberof_role',
associator: IPA.serial_associator
},
{
$type: 'association',
name: 'memberof_hbacrule',
associator: IPA.serial_associator,
add_method: 'add_user',
remove_method: 'remove_user'
},
{
$type: 'association',
name: 'memberof_sudorule',
associator: IPA.serial_associator,
add_method: 'add_user',
remove_method: 'remove_user'
}
],
standard_association_facets: true,
adder_dialog: {
$factory: IPA.group_adder_dialog,
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
},
{
$type: 'radio',
name: 'type',
label: '@i18n:objects.group.type',
flags: ['no_command'],
default_value: 'posix',
options: [
{
value: 'nonposix',
label: '@i18n:objects.group.nonposix'
},
{
value: 'external',
label: '@i18n:objects.group.external'
},
{
value: 'posix',
label: '@i18n:objects.group.posix'
}
]
},
'gidnumber'
]
}
};};
IPA.group_adder_dialog = function(spec) {
spec = spec || {};
var that = IPA.entity_adder_dialog(spec);
var init = function() {
var type_field = that.fields.get_field('type');
on(type_field, 'value-change', that.on_type_change);
};
that.on_type_change = function() {
var type_field = that.fields.get_field('type');
var gid_field = that.fields.get_field('gidnumber');
var posix = type_field.get_value()[0] === 'posix';
if (!posix) {
gid_field.reset();
}
gid_field.set_enabled(posix);
};
that.create_add_command = function(record) {
var command = that.entity_adder_dialog_create_add_command(record);
var type_field = that.fields.get_field('type');
var type = type_field.save()[0];
if (type === 'nonposix' || type === 'external') {
command.set_option(type, true);
}
return command;
};
init();
return that;
};
IPA.group.make_posix_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'make_posix';
spec.method = spec.method || 'mod';
spec.label = spec.label || '@i18n:objects.group.make_posix';
spec.needs_confirm = spec.needs_confirm !== undefined ? spec.needs_confirm : true;
spec.disable_cond = spec.disable_cond || ['oc_posixgroup', 'oc_ipaexternalgroup'];
spec.options = spec.options || {
posix: true
};
var that = IPA.object_action(spec);
return that;
};
IPA.group.make_external_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'make_external';
spec.method = spec.method || 'mod';
spec.label = spec.label || '@i18n:objects.group.make_external';
spec.needs_confirm = spec.needs_confirm !== undefined ? spec.needs_confirm : true;
spec.disable_cond = spec.disable_cond || ['oc_posixgroup','oc_ipaexternalgroup'];
spec.options = spec.options || {
external: true
};
var that = IPA.object_action(spec);
return that;
};
exp.entity_spec = make_spec();
exp.register = function() {
var e = reg.entity;
var a = reg.action;
e.register({ type: 'group', spec: exp.entity_spec });
a.register('make_posix', exp.make_posix_action);
a.register('make_external', exp.make_external_action);
};
phases.on('registration', exp.register);
return exp;
});

View File

@@ -0,0 +1,506 @@
/* Authors:
* Endi Sukma Dewata <edewata@redhat.com>
* Adam Young <ayoung@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./phases',
'./reg',
'./rpc',
'./association',
'./details',
'./entity',
'./rule',
'./search'
],
function(IPA, $, phases, reg, rpc) {
var exp = IPA.hbac = {
//priority of commands in details facet
remove_method_priority: IPA.config.default_priority - 1
};
var make_rule_spec = function() {
var spec = {
name: 'hbacrule',
facets: [
{
$type: 'search',
row_enabled_attribute: 'ipaenabledflag',
columns: [
'cn',
{
name: 'ipaenabledflag',
label: '@i18n:status.label',
formatter: 'boolean_status'
},
'description'
],
actions: [
'batch_disable',
'batch_enable'
],
control_buttons: [
{
name: 'disable',
label: '@i18n:buttons.disable',
icon: 'fa-minus'
},
{
name: 'enable',
label: '@i18n:buttons.enable',
icon: 'fa-check'
}
]
},
{
$type: 'details',
$factory: IPA.hbacrule_details_facet,
command_mode: 'info',
actions: [
'select',
'enable',
'disable',
'delete'
],
header_actions: ['enable', 'disable', 'delete'],
state: {
evaluators: [
{
$factory: IPA.enable_state_evaluator,
field: 'ipaenabledflag'
}
],
summary_conditions: [
IPA.enabled_summary_cond,
IPA.disabled_summary_cond
]
}
}
],
adder_dialog: {
fields: [ 'cn' ]
}
};
add_hbacrule_details_facet_widgets(spec.facets[1]);
return spec;
};
var make_service_spec = function() {
return {
name: 'hbacsvc',
facets: [
{
$type: 'search',
columns: [
'cn',
'description'
]
},
{
$type: 'details',
sections: [
{
name: 'general',
label: '@i18n:details.general',
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
]
},
{
$type: 'association',
name: 'memberof_hbacsvcgroup',
associator: IPA.serial_associator,
columns:[
'cn',
'description'
],
adder_columns: [
{
name: 'cn',
primary_key: true,
width: '100px'
},
{
name: 'description',
width: '100px'
}
]
}
],
standard_association_facets: true,
adder_dialog: {
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
};};
var make_service_group_spec = function() {
return {
name: 'hbacsvcgroup',
facets: [
{
$type: 'search',
columns: [
'cn',
'description'
]
},
{
$type: 'details',
sections: [
{
name: 'general',
label: '@i18n:details.general',
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
]
},
{
$type: 'association',
name: 'member_hbacsvc',
columns:[
'cn',
'description'
],
adder_columns: [
{
name: 'cn',
primary_key: true,
width: '100px'
},
{
name: 'description',
width: '100px'
}
]
}
],
standard_association_facets: true,
adder_dialog: {
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
};};
/**
* @ignore
* @param {Object} facet spec
*/
var add_hbacrule_details_facet_widgets = function (spec) {
//
// General
//
spec.fields = [
{
name: 'cn',
read_only: true,
widget: 'general.cn'
},
{
$type: 'textarea',
name: 'description',
widget: 'general.description'
}
];
spec.widgets = [
{
$type: 'details_section',
name: 'general',
label: '@i18n:details.general',
widgets: [
{
name: 'cn'
},
{
$type: 'textarea',
name: 'description'
}
]
}
];
//
// Users
//
spec.fields.push(
{
$type: 'radio',
name: 'usercategory',
widget: 'user.rule.usercategory'
},
{
$type: 'rule_association_table',
name: 'memberuser_user',
widget: 'user.rule.memberuser_user',
priority: IPA.hbac.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberuser_group',
widget: 'user.rule.memberuser_group',
priority: IPA.hbac.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'user',
label: '@i18n:objects.hbacrule.user',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'rule',
radio_name: 'usercategory',
options: [
{ value: 'all',
label: '@i18n:objects.hbacrule.anyone' },
{ value: '',
label: '@i18n:objects.hbacrule.specified_users' }
],
tables: [
{ name: 'memberuser_user' },
{ name: 'memberuser_group' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'hbacrule-memberuser_user',
name: 'memberuser_user',
add_method: 'add_user',
remove_method: 'remove_user',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
},
{
$type: 'rule_association_table',
id: 'hbacrule-memberuser_group',
name: 'memberuser_group',
add_method: 'add_user',
remove_method: 'remove_user',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
}
]
}
);
//
// Hosts
//
spec.fields.push(
{
$type: 'radio',
name: 'hostcategory',
widget: 'host.rule.hostcategory'
},
{
$type: 'rule_association_table',
name: 'memberhost_host',
widget: 'host.rule.memberhost_host',
priority: IPA.hbac.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberhost_hostgroup',
widget: 'host.rule.memberhost_hostgroup',
priority: IPA.hbac.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'host',
label: '@i18n:objects.hbacrule.host',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'rule',
radio_name: 'hostcategory',
options: [
{
'value': 'all',
'label': '@i18n:objects.hbacrule.any_host'
},
{
'value': '',
'label': '@i18n:objects.hbacrule.specified_hosts'
}
],
tables: [
{ 'name': 'memberhost_host' },
{ 'name': 'memberhost_hostgroup' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'hbacrule-memberuser_user',
name: 'memberhost_host',
add_method: 'add_host',
remove_method: 'remove_host',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
},
{
$type: 'rule_association_table',
id: 'hbacrule-memberuser_group',
name: 'memberhost_hostgroup',
add_method: 'add_host',
remove_method: 'remove_host',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
}
]
}
);
//
// Service
//
spec.fields.push(
{
$type: 'radio',
name: 'servicecategory',
widget: 'service.rule.servicecategory'
},
{
$type: 'rule_association_table',
name: 'memberservice_hbacsvc',
widget: 'service.rule.memberservice_hbacsvc',
priority: IPA.hbac.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberservice_hbacsvcgroup',
widget: 'service.rule.memberservice_hbacsvcgroup',
priority: IPA.hbac.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'service',
label: '@i18n:objects.hbacrule.service',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'rule',
radio_name: 'servicecategory',
options: [
{ 'value': 'all', 'label': '@i18n:objects.hbacrule.any_service' },
{ 'value': '', 'label': '@i18n:objects.hbacrule.specified_services' }
],
tables: [
{ 'name': 'memberservice_hbacsvc' },
{ 'name': 'memberservice_hbacsvcgroup' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'hbacrule-memberuser_user',
name: 'memberservice_hbacsvc',
add_method: 'add_service',
remove_method: 'remove_service',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
},
{
$type: 'rule_association_table',
id: 'hbacrule-memberuser_group',
name: 'memberservice_hbacsvcgroup',
add_method: 'add_service',
remove_method: 'remove_service',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
}
]
}
);
};
IPA.hbacrule_details_facet = function(spec) {
var that = IPA.details_facet(spec);
that.update_on_success = function(data, text_status, xhr) {
that.refresh();
that.on_update.notify();
that.nofify_update_success();
};
that.update_on_error = function(xhr, text_status, error_thrown) {
that.refresh();
};
return that;
};
exp.rule_spec = make_rule_spec();
exp.svc_spec = make_service_spec();
exp.svcgroup_spec = make_service_group_spec();
exp.register = function() {
var e = reg.entity;
e.register({type: 'hbacrule', spec: exp.rule_spec});
e.register({type: 'hbacsvc', spec: exp.svc_spec});
e.register({type: 'hbacsvcgroup', spec: exp.svcgroup_spec});
};
phases.on('registration', exp.register);
return exp;
});

View File

@@ -0,0 +1,822 @@
/* Authors:
* Endi Sukma Dewata <edewata@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./metadata',
'./ipa',
'./jquery',
'./navigation',
'./phases',
'./reg',
'./rpc',
'./text',
'./details',
'./search',
'./association',
'./entity',
'./hbac'],
function(metadata_provider, IPA, $, navigation, phases, reg, rpc, text) {
var exp = {};
var make_spec = function() {
return {
name: 'hbactest',
facet_groups: [ 'default' ],
facets: [
{
$factory: IPA.hbac.test_select_facet,
name: 'user',
label: '@i18n:objects.hbacrule.user',
managed_entity: 'user',
disable_breadcrumb: true,
facet_group: 'default',
row_disabled_attribute: 'nsaccountlock',
columns: [
'uid',
'givenname',
'sn',
{
name: 'nsaccountlock',
label: '@i18n:status.label',
formatter: {
$type: 'boolean_status',
invert_value: true
}
}
]
},
{
$factory: IPA.hbac.test_select_facet,
name: 'targethost',
label: '@i18n:objects.hbacrule.host',
managed_entity: 'host',
disable_breadcrumb: true,
facet_group: 'default',
columns: [
'fqdn',
'description',
{
name: 'has_keytab',
label: '@i18n:objects.host.enrolled',
formatter: 'boolean'
}
]
},
{
$factory: IPA.hbac.test_select_facet,
name: 'service',
label: '@i18n:objects.hbacrule.service',
managed_entity: 'hbacsvc',
disable_breadcrumb: true,
facet_group: 'default',
columns: [
'cn',
'description'
]
},
{
$factory: IPA.hbac.test_rules_facet,
name: 'rules',
label: '@i18n:objects.hbactest.rules',
managed_entity: 'hbacrule',
disable_breadcrumb: true,
facet_group: 'default',
row_enabled_attribute: 'ipaenabledflag',
columns: [
'cn',
{
name: 'ipaenabledflag',
label: '@i18n:status.label',
formatter: 'boolean_status'
},
'description'
]
},
{
$factory: IPA.hbac.test_run_facet,
name: 'run_test',
label: '@i18n:objects.hbactest.run_test',
managed_entity: 'hbacrule',
disable_breadcrumb: true,
facet_group: 'default',
row_enabled_attribute: 'ipaenabledflag',
columns: [
'cn',
{
name: 'matched',
label: '@i18n:objects.hbactest.matched',
formatter: 'boolean'
},
{
name: 'ipaenabledflag',
label: '@i18n:status.label',
formatter: 'boolean_status'
},
'description'
]
}
]
};};
IPA.hbac.test_entity = function(spec) {
var that = IPA.entity(spec);
that.label = text.get('@i18n:objects.hbactest.label');
that.get_default_metadata = function() {
return metadata_provider.get('@mc:'+that.name);
};
return that;
};
IPA.hbac.test_facet = function(spec) {
spec = spec || {};
var that = IPA.table_facet(spec);
var init = function() {
that.managed_entity = IPA.get_entity(that.managed_entity);
var columns = that.columns.values;
for (var i=0; i<columns.length; i++) {
var column = columns[i];
var metadata = IPA.get_entity_param(that.managed_entity.name, column.name);
column.primary_key = metadata && metadata.primary_key;
column.link = column.primary_key;
}
that.init_table(that.managed_entity);
};
that.create_buttons = function(container) {
var buttons = $('<div/>', {
'class': 'hbac-test-navigation-buttons'
}).appendTo(container);
var facet_group = that.entity.get_facet_group('default');
var index = facet_group.get_facet_index(that.name);
if (index > 0) {
that.prev_button = IPA.button({
name: 'prev',
label: '@i18n:widget.prev',
icon: 'fa-chevron-left',
click: that.prev
}).appendTo(buttons);
buttons.append(' ');
}
that.next_button = IPA.button({
name: 'next',
label: '@i18n:widget.next',
icon: 'fa-chevron-right',
click: that.next
}).appendTo(buttons);
};
that.prev = function() {
var facet_group = that.entity.get_facet_group('default');
var index = facet_group.get_facet_index(that.name);
if (index <= 0) return;
var facet = facet_group.get_facet_by_index(index - 1);
navigation.show(facet);
};
that.next = function() {
var facet_group = that.entity.get_facet_group('default');
var index = facet_group.get_facet_index(that.name);
if (index >= facet_group.get_facet_count() - 1) return;
var facet = facet_group.get_facet_by_index(index + 1);
navigation.show(facet);
};
that.get_search_command_name = function() {
return that.managed_entity.name + '_find' + (that.pagination ? '_pkeys' : '');
};
that.refresh = function() {
var filter = that.state.filter;
var command = rpc.command({
name: that.get_search_command_name(),
entity: that.managed_entity.name,
method: 'find',
args: [filter]
});
if (that.pagination) {
command.set_option('pkey_only', true);
command.set_option('sizelimit', 0);
}
command.on_success = function(data, text_status, xhr) {
that.load(data);
that.show_content();
};
command.on_error = function(xhr, text_status, error_thrown) {
that.report_error(error_thrown);
};
command.execute();
};
init();
return that;
};
IPA.hbac.test_select_facet = function(spec) {
var that = IPA.hbac.test_facet(spec);
var init = function() {
that.table.multivalued = false;
that.table.set_values = function(values) {
if (values && values.length && values[0] === '__external__') {
if (that.external_radio) that.external_radio.prop('checked', true);
} else {
that.table.table_set_values(values);
}
};
};
that.create_content = function(container) {
var header = $('<div/>', {
'class': 'hbac-test-header'
}).appendTo(container);
var title = $('<span/>', {
text: that.label,
'class': 'hbac-test-title'
}).appendTo(header);
var filter_container = $('<div/>', {
'class': 'search-filter'
}).appendTo(header);
that.filter = $('<input/>', {
type: 'text',
'class': 'form-control',
name: 'filter'
}).appendTo(filter_container);
that.filter.keypress(function(e) {
/* if the key pressed is the enter key */
if (e.which == 13) {
that.find();
}
});
that.find_button = IPA.action_button({
name: 'find',
icon: 'fa-search',
click: function() {
that.find();
return false;
}
}).appendTo(filter_container);
var content = $('<div/>', {
'class': 'hbac-test-content'
}).appendTo(container);
that.table.create(content);
var id = that.entity.name+'-'+that.name+'-external';
var pkey_name = that.managed_entity.metadata.primary_key;
var tr = $('<tr/>').appendTo(that.table.tfoot);
var td = $('<td/>', {
name: 'external',
colspan: that.columns.length + 1
}).appendTo(tr);
that.external_radio = $('<input/>', {
id: id,
type: 'radio',
name: pkey_name,
value: '__external__',
click: function() {
that.selected_values = [ that.external_radio.val() ];
}
}).appendTo(td);
var message = text.get('@i18n:objects.hbactest.specify_external');
message = message.replace('${entity}', that.managed_entity.metadata.label_singular);
$('<label/>', {
text: message+':',
'for': id
}).appendTo(td);
td.append(' ');
that.external_text = $('<input/>', {
name: id,
focus: function() {
that.external_radio.click();
}
}).appendTo(td);
var footer = $('<div/>', {
'class': 'hbac-test-footer'
}).appendTo(container);
that.create_buttons(footer);
};
that.find = function() {
var old_filter = that.state.filter;
var filter = that.filter.val();
that.set_expired_flag();
if (old_filter === filter) {
that.refresh();
} else {
that.state.set({filter: filter});
}
};
that.get_selected_values = function() {
var values = that.table.get_selected_values();
if (values && values.length) return values;
if (that.external_radio && that.external_radio.is(':checked')) {
return [ that.external_radio.val() ];
}
return [];
};
that.reset = function() {
delete that.selected_values;
if (that.external_radio) that.external_radio.prop('checked', false);
if (that.external_text) that.external_text.val('');
};
that.save = function(record) {
if (that.selected_values && that.selected_values.length) {
var value = that.selected_values[0];
if (that.external_radio && value === that.external_radio.val()) {
record[that.name] = that.external_text.val();
} else {
record[that.name] = value;
}
}
};
that.validate = function(record) {
if (record[that.name]) return true;
return false;
};
init();
return that;
};
IPA.hbac.test_rules_facet = function(spec) {
spec = spec || {};
var that = IPA.hbac.test_facet(spec);
var init = function() {
};
that.create_content = function(container) {
var header = $('<div/>', {
'class': 'hbac-test-header'
}).appendTo(container);
var title = $('<span/>', {
text: that.label,
'class': 'hbac-test-title'
}).appendTo(header);
header.append(' ');
that.enabled = $('<input/>', {
id: 'hbactest-rules-include-enabled',
type: 'checkbox',
name: 'enabled'
}).appendTo(header);
$('<label/>', {
'for': 'hbactest-rules-include-enabled',
text: text.get('@i18n:objects.hbactest.include_enabled')
}).appendTo(header);
that.disabled = $('<input/>', {
id: 'hbactest-rules-include-disabled',
type: 'checkbox',
name: 'disabled'
}).appendTo(header);
$('<label/>', {
'for': 'hbactest-rules-include-disabled',
text: text.get('@i18n:objects.hbactest.include_disabled')
}).appendTo(header);
var content = $('<div/>', {
'class': 'hbac-test-content'
}).appendTo(container);
that.table.create(content);
var footer = $('<div/>', {
'class': 'hbac-test-footer'
}).appendTo(container);
that.create_buttons(footer);
};
that.get_selected_values = function() {
return that.table.get_selected_values();
};
that.reset = function() {
delete that.selected_values;
if (that.enabled) that.enabled.prop('checked', false);
if (that.disabled) that.disabled.prop('checked', false);
};
that.save = function(record) {
if (that.selected_values && that.selected_values.length) {
record[that.name] = that.selected_values;
}
if (that.enabled && that.enabled.is(':checked')) {
record['enabled'] = true;
}
if (that.disabled && that.disabled.is(':checked')) {
record['disabled'] = true;
}
};
init();
return that;
};
IPA.hbac.test_run_facet = function(spec) {
spec = spec || {};
var that = IPA.hbac.test_facet(spec);
var init = function() {
that.table.selectable = false;
that.show_matched = true;
that.show_unmatched = true;
};
that.create_content = function(container) {
var header = $('<div/>', {
'class': 'hbac-test-header'
}).appendTo(container);
var top_panel = $('<div/>', {
'class': 'hbac-test-top-panel row'
}).appendTo(header);
var button_panel = $('<div/>', {
'class': 'hbac-test-button-panel col-sm-2'
}).appendTo(top_panel);
that.run_button = IPA.button({
name: 'run_test',
label: '@i18n:objects.hbactest.run_test',
icon: 'fa-gear',
click: that.run
}).appendTo(button_panel);
var result_panel = $('<div/>', {
'class': 'hbac-test-result-panel col-sm-10'
}).appendTo(top_panel);
that.test_result = $('<p/>', {
'class': 'hbac-test-title'
}).appendTo(result_panel);
var title = $('<span/>', {
text: text.get('@i18n:objects.hbactest.rules'),
'class': 'hbac-test-title'
}).appendTo(header);
header.append(' ');
that.matched_checkbox = $('<input/>', {
id: 'hbactest-rules-matched',
type: 'checkbox',
name: 'matched',
checked: true,
change: function() {
that.show_matched = that.matched_checkbox.is(':checked');
that.refresh();
}
}).appendTo(header);
$('<label/>', {
'for': 'hbactest-rules-matched',
text: text.get('@i18n:objects.hbactest.matched')
}).appendTo(header);
that.unmatched_checkbox = $('<input/>', {
id: 'hbactest-rules-unmatched',
type: 'checkbox',
name: 'unmatched',
checked: true,
change: function() {
that.show_unmatched = that.unmatched_checkbox.is(':checked');
that.refresh();
}
}).appendTo(header);
$('<label/>', {
'for': 'hbactest-rules-unmatched',
text: text.get('@i18n:objects.hbactest.unmatched')
}).appendTo(header);
var content = $('<div/>', {
'class': 'hbac-test-content'
}).appendTo(container);
that.table.create(content);
var footer = $('<div/>', {
'class': 'hbac-test-footer'
}).appendTo(container);
var buttons = $('<div/>', {
'class': 'hbac-test-navigation-buttons'
}).appendTo(footer);
that.prev_button = IPA.button({
name: 'prev',
label: '@i18n:widget.prev',
icon: 'fa-chevron-left',
click: that.prev
}).appendTo(buttons);
buttons.append(' ');
that.new_test_button = IPA.button({
name: 'new_test',
label: '@i18n:objects.hbactest.new_test',
icon: 'fa-repeat',
click: that.new_test
}).appendTo(buttons);
};
that.new_test = function() {
var facet = that.entity.get_facet('user');
facet.reset();
var entry_point = facet;
facet = that.entity.get_facet('targethost');
facet.reset();
facet = that.entity.get_facet('service');
facet.reset();
facet = that.entity.get_facet('rules');
facet.reset();
facet = that.entity.get_facet('run_test');
facet.reset();
navigation.show(entry_point);
};
that.reset = function() {
delete that.data;
that.show_matched = true;
that.show_unmatched = true;
if (that.matched_checkbox) that.matched_checkbox.prop('checked', true);
if (that.unmatched_checkbox) that.unmatched_checkbox.prop('checked', true);
that.refresh();
};
that.refresh = function() {
if (that.data) {
var message = that.data.result.value ?
text.get('@i18n:objects.hbactest.access_granted') :
text.get('@i18n:objects.hbactest.access_denied');
that.test_result.text(message);
} else {
that.test_result.text('');
}
that.load(that.data);
};
that.run = function() {
var command = rpc.command({ method: 'hbactest' });
var options = {};
var validation_results = {
valid: true,
invalid_facets: []
};
var facet = that.entity.get_facet('user');
facet.save(options);
that.validate_facet(facet, options, validation_results);
facet = that.entity.get_facet('targethost');
facet.save(options);
that.validate_facet(facet, options, validation_results);
facet = that.entity.get_facet('service');
facet.save(options);
that.validate_facet(facet, options, validation_results);
if (!validation_results.valid) {
var dialog = IPA.hbac.validation_dialog({
validation_results: validation_results
});
dialog.open();
return;
}
facet = that.entity.get_facet('rules');
facet.save(options);
command.set_options(options);
command.on_success = function(data, text_status, xhr) {
that.data = data;
that.refresh();
};
command.execute();
};
that.validate_facet = function(facet, options, validation_results) {
var facet_valid = facet.validate(options);
validation_results.valid = facet_valid && validation_results.valid;
if (!facet_valid) {
validation_results.invalid_facets.push(facet);
}
};
that.get_records_map = function(data) {
var records_map = $.ordered_map();
var pkeys_map = $.ordered_map();
var matched = data.result.matched;
if (that.show_matched && matched) {
for (var i=0; i<matched.length; i++) {
var pkey = matched[i];
var compound_pkey = pkey + i;
records_map.put(compound_pkey, { matched: true });
pkeys_map.put(compound_pkey, pkey);
}
}
var notmatched = data.result.notmatched;
if (that.show_unmatched && notmatched) {
for (i=0; i<notmatched.length; i++) {
pkey = notmatched[i];
compound_pkey = pkey + i;
records_map.put(compound_pkey, { matched: false });
pkeys_map.put(compound_pkey, pkey);
}
}
return {
records_map: records_map,
pkeys_map: pkeys_map
};
};
that.get_records_command_name = function() {
if (that.show_matched && !that.show_unmatched) {
return 'hbactest_matched';
}
if (!that.show_matched && that.show_unmatched) {
return 'hbactest_unmatched';
}
return that.managed_entity.name+'_get_records';
};
init();
return that;
};
IPA.hbac.validation_dialog = function(spec) {
spec = spec || {};
spec.title = spec.title || '@i18n:dialogs.validation_title';
spec.message = spec.message || '@i18n:dialogs.validation_message';
var that = IPA.message_dialog(spec);
that.validation_results = spec.validation_results;
that.create_content = function() {
if (that.message) {
that.message_dialog_create_content();
}
if (that.validation_results && that.validation_results.invalid_facets) {
var invalid_facets = that.validation_results.invalid_facets;
var ul;
if (invalid_facets.length > 0) {
var div = $('<div/>',{
text: text.get('@i18n:objects.hbactest.missing_values')
}).appendTo(that.container);
ul = $('<ul/>').appendTo(that.container);
}
for (var i=0; i<invalid_facets.length; i++) {
var facet = invalid_facets[i];
var li = $('<li />').appendTo(ul);
var metadata = IPA.get_command_option('hbactest', facet.name);
$('<a />', {
href: '#'+facet.name,
text: metadata.label,
click: function(facet) {
return function() {
that.redirect_to_facet(facet);
return false;
};
}(facet)
}).appendTo(li);
}
}
};
that.redirect_to_facet = function(facet) {
that.close();
navigation.show(facet);
};
return that;
};
exp.entity_spec = make_spec();
exp.register = function() {
var e = reg.entity;
e.register({
type: 'hbactest',
factory: IPA.hbac.test_entity,
spec: exp.entity_spec
});
};
phases.on('registration', exp.register);
return exp;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,112 @@
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./phases',
'./reg',
'./details',
'./search',
'./association',
'./entity'],
function(IPA, $, phases, reg) {
var exp = IPA.hostgroup = {};
var make_spec = function() {
return {
name: 'hostgroup',
facets: [
{
$type: 'search',
tab_label: '@i18n:objects.hostgroup.host_group',
facet_groups: [IPA.group.search_facet_group],
tabs_in_sidebar: true,
disable_facet_tabs: false,
columns: [
'cn',
'description'
]
},
{
$type: 'details',
sections: [
{
name: 'identity',
label: '@i18n:objects.hostgroup.identity',
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
]
},
{
$type: 'association',
name: 'memberof_hostgroup',
associator: IPA.serial_associator
},
{
$type: 'association',
name: 'memberof_netgroup',
associator: IPA.serial_associator
},
{
$type: 'association',
name: 'memberof_hbacrule',
associator: IPA.serial_associator,
add_method: 'add_host',
remove_method: 'remove_host'
},
{
$type: 'association',
name: 'memberof_sudorule',
associator: IPA.serial_associator,
add_method: 'add_host',
remove_method: 'remove_host'
}
],
standard_association_facets: true,
adder_dialog: {
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
};};
exp.entity_spec = make_spec();
exp.register = function() {
var e = reg.entity;
e.register({type: 'hostgroup', spec: exp.entity_spec});
};
phases.on('registration', exp.register);
return exp;
});

View File

@@ -0,0 +1,282 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/on',
'./ipa',
'./jquery',
'./phases',
'./reg',
'./details',
'./search',
'./association',
'./entity'],
function(on, IPA, $, phases, reg) {
var exp = IPA.idrange = {};
var make_spec = function() {
return {
name: 'idrange',
facets: [
{
$type: 'search',
columns: [
'cn',
'ipabaseid',
'ipaidrangesize',
'iparangetype'
]
},
{
$type: 'details',
sections: [
{
name: 'details',
fields: [
'cn',
'iparangetype',
{
name: 'iparangetyperaw',
read_only: true,
visible: false
},
{
name: 'ipabaseid',
label: '@i18n:objects.idrange.ipabaseid',
title: '@mo-param:idrange:ipabaseid:label'
},
{
name: 'ipaidrangesize',
label: '@i18n:objects.idrange.ipaidrangesize',
title: '@mo-param:idrange:ipaidrangesize:label'
},
{
name: 'ipabaserid',
label: '@i18n:objects.idrange.ipabaserid',
title: '@mo-param:idrange:ipabaserid:label'
},
{
name: 'ipasecondarybaserid',
label: '@i18n:objects.idrange.ipasecondarybaserid',
title: '@mo-param:idrange:ipasecondarybaserid:label'
},
{
name: 'ipanttrusteddomainsid',
label: '@i18n:objects.idrange.ipanttrusteddomainsid',
title: '@mo-param:idrange:ipanttrusteddomainsid:label'
}
]
}
],
policies: [
exp.idrange_policy
]
}
],
adder_dialog: {
fields: [
{
name: 'cn'
},
{
name: 'iparangetype',
$type: 'radio',
label: '@i18n:objects.idrange.type',
layout: 'vertical',
default_value: 'ipa-local',
options: [
{
value: 'ipa-local',
label: '@i18n:objects.idrange.type_local'
},
{
value: 'ipa-ad-trust',
label: '@i18n:objects.idrange.type_ad'
},
{
value: 'ipa-ad-trust-posix',
label: '@i18n:objects.idrange.type_ad_posix'
}
]
},
{
name: 'ipabaseid',
label: '@i18n:objects.idrange.ipabaseid',
title: '@mo-param:idrange:ipabaseid:label'
},
{
name: 'ipaidrangesize',
label: '@i18n:objects.idrange.ipaidrangesize',
title: '@mo-param:idrange:ipaidrangesize:label'
},
{
name: 'ipabaserid',
label: '@i18n:objects.idrange.ipabaserid',
title: '@mo-param:idrange:ipabaserid:label'
},
{
name: 'ipasecondarybaserid',
label: '@i18n:objects.idrange.ipasecondarybaserid',
title: '@mo-param:idrange:ipasecondarybaserid:label'
},
{
name: 'ipanttrusteddomainname',
enabled: false
}
],
policies: [
IPA.idrange_adder_policy
]
}
};};
IPA.idrange_adder_policy = function(spec) {
/*
The logic for enabling/requiring ipabaserid, ipasecondarybaserid and
ipanttrusteddomainname is as follows:
1) for AD ranges (range type is ipa-ad-trust or ipa-ad-trust-posix):
* ipanttrusteddomainname is required
* ipabaserid is required for ipa-ad-trust but disabled for
ipa-ad-trust-posix
* ipasecondarybaserid is disabled
2) for local ranges
* ipanttrusteddomainname is disabled
A) if server has AD trust support:
* both ipabaserid and ipasecondarybaserid are required
B) if server does not have AD trust support:
* ipabaserid and ipasecondarybaserid may only be used together
(if one is set, other is required and vice versa)
*/
function require(field) {
field.set_enabled(true);
field.set_required(true);
}
function disable(field) {
field.set_value(['']); // avoid usage of reset() to break event handler loop
field.set_required(false);
field.set_enabled(false);
}
function enable(field) {
field.set_enabled(true);
field.set_required(false);
}
spec = spec || {};
var that = IPA.facet_policy(spec);
that.init = function() {
var type_f = that.container.fields.get_field('iparangetype');
var baserid_f = that.container.fields.get_field('ipabaserid');
var secondarybaserid_f = that.container.fields.get_field('ipasecondarybaserid');
if (IPA.trust_enabled) {
require(baserid_f);
require(secondarybaserid_f);
}
on(type_f, 'value-change', that.on_input_change);
on(baserid_f, 'value-change', that.on_input_change);
on(secondarybaserid_f, 'value-change', that.on_input_change);
};
that.on_input_change = function() {
var type_f = that.container.fields.get_field('iparangetype');
var baserid_f = that.container.fields.get_field('ipabaserid');
var secondarybaserid_f = that.container.fields.get_field('ipasecondarybaserid');
var trusteddomainname_f = that.container.fields.get_field('ipanttrusteddomainname');
var type_v = type_f.get_value()[0];
var baserid_v = baserid_f.get_value()[0] || '';
var secondarybaserid_v = secondarybaserid_f.get_value()[0] || '';
var is_ad_range = (type_v === 'ipa-ad-trust' || type_v === 'ipa-ad-trust-posix');
if (is_ad_range) {
if (type_v === 'ipa-ad-trust') {
require(baserid_f);
} else {
disable(baserid_f);
}
require(trusteddomainname_f);
disable(secondarybaserid_f);
} else {
disable(trusteddomainname_f);
if (IPA.trust_enabled) {
require(baserid_f);
require(secondarybaserid_f);
} else {
if (baserid_v || secondarybaserid_v) {
require(baserid_f);
require(secondarybaserid_f);
} else {
enable(baserid_f);
enable(secondarybaserid_f);
}
}
}
};
return that;
};
exp.idrange_policy = function(spec) {
spec = spec || {};
var that = IPA.facet_policy(spec);
that.post_load = function() {
var type_f = that.container.fields.get_field('iparangetyperaw');
var widgets = that.container.widgets;
var type_v = type_f.get_value()[0];
var baserid = true;
var secrid = true;
var sid = true;
if (type_v === 'ipa-local') {
sid = false;
} else if (type_v === 'ipa-ad-trust-posix') {
baserid = secrid = false;
} else if (type_v === 'ipa-ad-trust') {
secrid = false;
}
widgets.get_widget('details.ipabaserid').set_visible(baserid);
widgets.get_widget('details.ipasecondarybaserid').set_visible(secrid);
widgets.get_widget('details.ipanttrusteddomainsid').set_visible(sid);
};
return that;
};
exp.entity_spec = make_spec();
exp.register = function() {
var e = reg.entity;
e.register({type: 'idrange', spec: exp.entity_spec});
};
phases.on('registration', exp.register);
return {};
});

View File

@@ -0,0 +1,989 @@
/*
* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2014 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/on',
'./ipa',
'./builder',
'./jquery',
'./menu',
'./phases',
'./reg',
'./rpc',
'./text',
'./details',
'./facet',
'./search',
'./entity'],
function(on, IPA, builder, $, menu, phases, reg, rpc, text,
mod_details, mod_facet) {
/**
* ID Views module
* @class
* @singleton
*/
var idviews = IPA.idviews = {
DEFAULT_TRUST_VIEW: 'Default Trust View'
};
var make_spec = function() {
return {
name: 'idview',
enable_test: function() {
return true;
},
facet_groups: [
{
name: 'overrides',
label: '@i18n:objects.idview.overrides_tab'
},
{
name: 'appliedto',
label: '@i18n:objects.idview.appliesto_tab'
},
'settings'
],
facets: [
{
$type: 'search',
columns: [
'cn',
'description'
],
actions: [
'idview_unapply_host',
'idview_unapply_hostgroups'
],
control_buttons: [
{
name: 'idview_unapply_host',
label: '@i18n:objects.idview.unapply_hosts_all',
icon: 'fa-trash-o'
},
{
name: 'idview_unapply_hostgroups',
label: '@i18n:objects.idview.unapply_hostgroups',
icon: 'fa-trash-o'
}
]
},
{
$type: 'details',
header: idviews.idview_facet_header,
actions: [
'delete'
],
header_actions: ['delete'],
state: {
},
sections: [
{
name: 'details',
fields: [
'cn',
{
name: 'ipadomainresolutionorder',
flags: ['w_if_no_aci'],
tooltip: '@mc-opt:idview_mod:ipadomainresolutionorder:doc'
},
{
$type: 'textarea',
name: 'description'
}
]
}
]
},
{
$type: 'nested_search',
facet_group: 'overrides',
header: idviews.idview_facet_header,
nested_entity: 'idoverrideuser',
search_all_entries: true,
label: '@mo:idoverrideuser.label',
tab_label: '@mo:user.label',
name: 'idoverrideuser',
columns: [
{
name: 'ipaanchoruuid',
label: '@i18n:objects.idoverrideuser.anchor_label'
},
'uid',
'uidnumber',
'homedirectory',
'description'
]
},
{
$type: 'nested_search',
facet_group: 'overrides',
header: idviews.idview_facet_header,
nested_entity: 'idoverridegroup',
search_all_entries: true,
label: '@mo:idoverridegroup.label',
tab_label: '@mo:group.label',
name: 'idoverridegroup',
columns: [
{
name: 'ipaanchoruuid',
label: '@i18n:objects.idoverridegroup.anchor_label'
},
'cn',
'gidnumber',
'description'
]
},
{
$type: 'idview_appliedtohosts',
name: 'appliedtohosts',
attribute: 'appliedtohosts',
tab_label: '@mo:host.label',
facet_group: 'appliedto',
actions: [
'idview_apply',
'idview_apply_hostgroups',
'idview_unapply',
'idview_unapply_hostgroups'
],
control_buttons: [
{
name: 'idview_unapply',
label: '@i18n:objects.idview.unapply_hosts',
icon: 'fa-trash-o'
},
{
name: 'idview_unapply_hostgroups',
label: '@i18n:objects.idview.unapply_hostgroups',
icon: 'fa-trash-o'
},
{
name: 'idview_apply',
label: '@i18n:objects.idview.apply_hosts',
icon: 'fa-plus'
},
{
name: 'idview_apply_hostgroups',
label: '@i18n:objects.idview.apply_hostgroups',
icon: 'fa-plus'
}
],
columns: [
{
name: 'appliedtohosts',
label: '@mo:host.label_singular',
link: true,
target_entity: 'host',
target_facet: 'details'
}
],
state: {
evaluators: [
{
$factory: mod_details.value_state_evaluator,
attribute: 'cn',
value: idviews.DEFAULT_TRUST_VIEW,
representation: 'cn_default_trust_view'
}
]
}
}
],
adder_dialog: {
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
};};
var make_idoverrideuser_spec = function() {
return {
name: 'idoverrideuser',
enable_test: function() {
return true;
},
policies:[
{
$factory: IPA.facet_update_policy,
source_facet: 'details',
dest_entity: 'idview',
dest_facet: 'idoverrideuser'
},
{
$factory: IPA.cert.cert_update_policy,
source_facet: 'details',
dest_entity: 'cert',
dest_facet: 'search'
}
],
containing_entity: 'idview',
facets: [
{
$factory: idviews.id_override_user_details_facet,
$type: 'details',
disable_breadcrumb: false,
containing_facet: 'idoverrideuser',
actions: [
'delete'
],
header_actions: ['delete'],
state: {
},
sections: [
{
name: 'details',
fields: [
{
$type: 'link',
name: 'ipaanchoruuid',
label: '@i18n:objects.idoverrideuser.anchor_label',
other_entity: 'user'
},
{
$type: 'textarea',
name: 'description'
},
'uid',
'gecos',
'uidnumber',
'gidnumber',
'loginshell',
'homedirectory',
{
$type: 'sshkeys',
name: 'ipasshpubkey',
label: '@i18n:objects.sshkeystore.keys'
},
{
$type: 'idviews_certs',
name: 'usercertificate',
label: '@i18n:objects.cert.certificates'
}
]
}
]
}
],
adder_dialog: {
policies: [
{ $factory: idviews.idoverride_adder_policy }
],
fields: [
{
$type: 'entity_select',
label: '@i18n:objects.idoverrideuser.anchor_label',
name: 'ipaanchoruuid',
other_entity: 'user',
other_field: 'uid',
editable: true,
tooltip: '@i18n:objects.idoverrideuser.anchor_tooltip'
},
{
label: '@i18n:objects.idoverrideuser.anchor_label',
name: 'ipaanchoruuid_default',
param: 'ipaanchoruuid',
tooltip: '@i18n:objects.idoverrideuser.anchor_tooltip_ad',
visible: false,
enabled: false
},
'uid',
'gecos',
'uidnumber',
'gidnumber',
{
$type: 'cert_textarea',
name: 'usercertificate'
},
'loginshell',
'homedirectory',
{
$type: 'textarea',
name: 'description'
}
]
}
};};
var make_idoverridegroup_spec = function() {
return {
name: 'idoverridegroup',
enable_test: function() {
return true;
},
policies:[
{
$factory: IPA.facet_update_policy,
source_facet: 'details',
dest_entity: 'idview',
dest_facet: 'idoverridegroup'
}
],
containing_entity: 'idview',
facets: [
{
$type: 'details',
disable_breadcrumb: false,
containing_facet: 'idoverridegroup',
actions: [
'delete'
],
header_actions: ['delete'],
state: {
},
sections: [
{
name: 'details',
fields: [
{
$type: 'link',
name: 'ipaanchoruuid',
label: '@i18n:objects.idoverridegroup.anchor_label',
other_entity: 'group'
},
{
$type: 'textarea',
name: 'description'
},
'cn',
'gidnumber'
]
}
]
}
],
adder_dialog: {
policies: [
{ $factory: idviews.idoverride_adder_policy }
],
fields: [
{
$type: 'entity_select',
label: '@i18n:objects.idoverridegroup.anchor_label',
name: 'ipaanchoruuid',
other_entity: 'group',
other_field: 'cn',
editable: true,
tooltip: '@i18n:objects.idoverridegroup.anchor_tooltip'
},
{
label: '@i18n:objects.idoverridegroup.anchor_label',
name: 'ipaanchoruuid_default',
param: 'ipaanchoruuid',
tooltip: '@i18n:objects.idoverridegroup.anchor_tooltip_ad',
visible: false,
enabled: false
},
'cn',
'gidnumber',
{
$type: 'textarea',
name: 'description'
}
]
}
};};
/**
* Facet for User ID override, uses batch command to fetch certificates.
*
* @class
* @extends IPA.details_facet
*/
idviews.id_override_user_details_facet = function(spec) {
spec = spec || {};
var that = IPA.details_facet(spec);
that.certificate_updated = IPA.observer();
that.create_refresh_command = function() {
var user_command = that.details_facet_create_refresh_command();
var batch = rpc.batch_command({
name: that.entity.name + "_details_refresh"
});
batch.add_command(user_command);
var pkey = that.get_pkey();
var certs = rpc.command({
entity: 'cert',
method: 'find',
retry: false,
options: {
idoverrideuser: [ pkey ],
sizelimit: 0,
all: true
}
});
batch.add_command(certs);
return batch;
};
return that;
};
idviews.aduser_idoverrideuser_pre_op = function(spec, context) {
spec = spec || [];
if (!IPA.is_aduser_selfservice) return spec;
var facet = spec.facets[0];
facet.label = '@i18n:objects.idoverrideuser.profile';
facet.actions = [];
facet.header_actions = [];
facet.disable_breadcrumb = true;
return spec;
};
/**
* @extends IPA.cert.certs_widget
*/
idviews.idviews_certs_widget = function(spec) {
spec = spec || {};
spec.child_spec = {
$factory: idviews.idviews_cert_widget,
css_class: 'certificate-widget',
facet: spec.facet
};
var that = IPA.cert.certs_widget(spec);
/* Adds two args to add command - special nested entities. */
that.create_add_args = function() {
return that.facet.get_pkeys();
};
/* Adds two args to remove command - special nested entities. */
that.create_remove_args = function() {
return that.facet.get_pkeys();
};
return that;
};
/**
* This widget uses cert_find instead of cert_show, because cert_show does not
* support nested entities.
*
* @extends IPA.cert.cert_widget
*/
idviews.idviews_cert_widget = function(spec) {
spec = spec || {};
var that = IPA.cert.cert_widget(spec);
that.adapter = builder.build('adapter', spec.adapter || 'object_adapter', {});
that.fetch_certificate_data = function(cert) {
var result = {};
var adapter = that.adapter;
if (!cert) return;
var command = rpc.command({
entity: 'cert',
method: 'find',
options: {
certificate: cert,
all: true
},
hide_activity_icon: true,
on_success: function(data) {
var normalized_data = adapter.load(data);
that.certificate = $.extend(normalized_data[0], {});
that.update_displayed_data();
that.spinner.emit('hide-spinner');
},
on_error: function() {
that.update_displayed_data();
that.spinner.emit('hide-spinner');
}
}).execute();
};
that.update = function(values) {
that.spinner.emit('display-spinner');
var certificate = values[0];
that.fetch_certificate_data(certificate);
};
that.save = function() {
if (!that.certificate) return '';
return that.certificate.certificate;
};
return that;
};
idviews.cert_textarea_widget = function(spec) {
spec = spec || {};
var that = IPA.textarea_widget(spec);
that.save = function() {
var value = that.input.val();
var blob = IPA.cert.get_base64(value);
return [blob];
};
return that;
};
/**
* Facet for hosts which have current id view applied on
*
* @class idviews.appliedtohosts_facet
* @extends IPA.attribute_facet
*/
idviews.appliedtohosts_facet = function(spec, no_init) {
spec = spec || {};
var that = IPA.attribute_facet(spec, no_init);
/**
* @inheritDoc
*/
that.get_refresh_command = function() {
var command = that.attribute_get_refresh_command();
command.set_option('show_hosts', true);
return command;
};
return that;
};
idviews.idview_facet_header = function(spec) {
var that = mod_facet.facet_header(spec);
/**
* Set pkeys and hides 'appliedtohosts' facet for 'Default Trust View'
* @param {string} value pkey
*/
that.set_pkey = function(value) {
that.facet_header_set_pkey(value);
var display = value === idviews.DEFAULT_TRUST_VIEW ? 'none' : '';
$('.facet-group[name="appliedto"]', that.facet_tabs).
css('display', display);
};
return that;
};
/**
* Switches between combobox and textbox for ipaanchoruuid, depending on if
* current view is Default Trust View
* @class idviews.idoverride_adder_policy
* @extends IPA.facet_policy
*/
idviews.idoverride_adder_policy = function (spec) {
var that = IPA.facet_policy(spec);
that.init = function() {
on(that.container, 'open', that.on_open);
};
that.on_open = function() {
var d = that.container; // dialog
var default_view = d.pkey_prefix.slice(-1)[0] === idviews.DEFAULT_TRUST_VIEW;
var f1 = d.fields.get_field('ipaanchoruuid');
var f2 = d.fields.get_field('ipaanchoruuid_default');
f1.set_enabled(!default_view);
f1.widget.set_visible(!default_view);
f2.set_enabled(default_view);
f2.widget.set_visible(default_view);
};
return that;
};
/**
* Apply Id view on hosts on hostgroup action base class
*
* @class idviews.apply_action
* @extends IPA.action
*/
idviews.apply_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'idview_apply';
spec.label = spec.label || '@i18n:objects.idview.apply_hosts';
spec.hide_cond = spec.hide_cond || ['cn_default_trust_view'];
var that = IPA.action(spec);
/**
* Confirm button label
* @property {string}
*/
that.confirm_button_label = spec.confirm_button_label || '@i18n:buttons.apply';
/**
* Entity to apply
* @property {entity.entity|string}
*/
that.other_entity = spec.other_entity || 'host';
/**
* Dialog title
* @property {string}
*/
that.dialog_title = spec.dialog_title || '@i18n:objects.idview.apply_hosts_title';
/**
* Method
* @property {string}
*/
that.method = spec.method || 'apply';
/**
* Success message
* @property {string}
*/
that.success_msg = spec.success_msg || '@i18n:association.added';
/**
* @inheritDoc
*/
that.execute_action = function(facet, on_success, on_error) {
that.show_dialog(facet);
};
/**
* Create and open dialog
*/
that.show_dialog = function(facet) {
var pkey = facet.get_pkey();
var other_entity = reg.entity.get(that.other_entity);
var other_entity_label = other_entity.metadata.label;
var exclude = that.get_exclude(facet);
var title = text.get(that.dialog_title);
title = title.replace('${entity}', other_entity_label);
title = title.replace('${primary_key}', pkey);
var dialog = IPA.association_adder_dialog({
title: title,
entity: facet.entity,
pkey: pkey,
other_entity: other_entity,
attribute_member: that.attribute_member,
exclude: exclude,
add_button_label: that.confirm_button_label
});
dialog.execute = function() {
var values = dialog.get_selected_values();
var command = that.get_command(
facet,
values,
function(data) {
that.notify_change(facet);
dialog.close();
var succeeded = IPA.get_succeeded(data);
var msg = text.get(that.success_msg).replace('${count}', succeeded);
IPA.notify_success(msg);
},
function() {
that.notify_change(facet);
dialog.close();
});
command.execute();
return command;
};
dialog.open();
};
/**
* Construct action command
*/
that.get_command = function(facet, values, on_success, on_error) {
var other_entity = reg.entity.get(that.other_entity);
var pkey = facet.get_pkey();
var args = pkey ? [pkey] : [];
var command = rpc.command({
entity: 'idview',
method: that.method,
args: args,
options: {},
on_success: on_success,
on_error: on_error
});
command.set_option(other_entity.name, values);
return command;
};
/**
* Get pkeys which should be excluded from offered pkeys in the dialog
*
* By default it works only for 'host' of 'appliedtohosts' facet since
* other facets might contain completely different values or might have
* different API.
*
* @param {facet.facet} facet
* @return {string[]}
*/
that.get_exclude = function(facet) {
if (facet && facet.name === 'appliedtohosts' &&
that.other_entity === 'host') {
var records = facet.get_records_map(facet.data);
return records.keys;
}
return [];
};
/**
* Notify idview.appliedtohosts facet that there were possible changes
* and a refresh is needed.
*/
that.notify_change = function(current_facet) {
if (current_facet && current_facet.name === 'appliedtohosts') {
current_facet.refresh();
} else {
reg.entity.get('idview').
get_facet('appliedtohosts').
set_expired_flag();
}
};
that.apply_action_get_command = that.get_command;
return that;
};
/**
* Apply Id view on hosts of a hostgroup
*
* @class idviews.apply_hostgroup_action
* @extends idviews.apply_action
*/
idviews.apply_hostgroups_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'idview_apply_hostgroups';
spec.label = spec.label || '@i18n:objects.idview.apply_hostgroups';
spec.other_entity = spec.other_entity || 'hostgroup';
spec.dialog_title = spec.dialog_title || '@i18n:objects.idview.apply_hostgroups_title';
var that = idviews.apply_action(spec);
return that;
};
/**
* Unapply Id view from hosts
*
* @class idviews.unapply_host_action
* @extends idviews.apply_action
*/
idviews.unapply_host_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'idview_unapply_host';
spec.label = spec.label || '@i18n:objects.idview.unapply_hosts_all';
spec.other_entity = spec.other_entity || 'host';
spec.method = spec.method || 'unapply';
spec.dialog_title = spec.dialog_title || '@i18n:objects.idview.unapply_hosts_all_title';
spec.confirm_button_label = spec.confirm_button_label || '@i18n:buttons.unapply';
spec.success_msg = spec.success_msg || '@i18n:association.removed';
var that = idviews.apply_action(spec);
/**
* @inheritDoc
*/
that.get_command = function(facet, values, on_success, on_error) {
var command = that.apply_action_get_command(facet, values, on_success, on_error);
// idview_unapply doesn't support primary keys to narrow down idviews
// to un-apply yet
command.args = [];
return command;
};
return that;
};
/**
* Unapply Id view from all hosts of a hostgroup
*
* @class idviews.unapply_hostgroups_action
* @extends idviews.unapply_host_action
*/
idviews.unapply_hostgroups_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'idview_unapply_hostgroups';
spec.label = spec.label || '@i18n:objects.idview.unapply_hostgroups';
spec.other_entity = spec.other_entity || 'hostgroup';
spec.dialog_title = spec.dialog_title || '@i18n:objects.idview.unapply_hostgroups_all_title';
var that = idviews.unapply_host_action(spec);
return that;
};
/**
* Unapply Id view from selected hosts
*
* @class idviews.unapply_action
* @extends idviews.unapply_host_action
*/
idviews.unapply_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'idview_unapply';
spec.label = spec.label || '@i18n:objects.idview.unapply_hosts';
spec.enable_cond = spec.enable_cond || ['item-selected'];
spec.enabled = spec.enabled === undefined ? false : spec.enabled;
spec.confirm_button_label = spec.confirm_button_label || '@i18n:buttons.unapply';
spec.method = spec.method || 'unapply';
spec.dialog_title = spec.dialog_title || '@i18n:objects.idview.unapply_hosts_title';
var that = idviews.unapply_host_action(spec);
/**
* @inheritDoc
*/
that.show_dialog = function(facet, current_pkeys) {
var selected_values = facet.get_selected_values();
if (!selected_values.length) {
var message = text.get('@i18n:dialogs.remove_empty');
IPA.notify(message, 'error');
return;
}
var pkey = facet.get_pkey();
var other_entity = reg.entity.get('host');
var title = text.get(that.dialog_title);
title = title.replace('${primary_key}', pkey);
var dialog = IPA.association_deleter_dialog({
title: title,
entity: facet.entity,
pkey: pkey,
other_entity: other_entity,
values: selected_values,
method: that.method,
ok_label: that.confirm_button_label,
message: '@i18n:objects.idview.unapply_hosts_confirm'
});
dialog.execute = function() {
var command = that.get_command(
facet,
selected_values,
function(data) {
that.notify_change(facet);
var succeeded = IPA.get_succeeded(data);
var msg = text.get('@i18n:association.removed').replace('${count}', succeeded);
IPA.notify_success(msg);
},
function() {
that.notify_change(facet);
}
);
command.execute();
};
dialog.open();
};
return that;
};
/**
* ID View entity specification object
* @member idviews
*/
idviews.spec = make_spec();
/**
* ID user override entity specification object
* @member idviews
*/
idviews.idoverrideuser_spec = make_idoverrideuser_spec();
/**
* ID group override entity specification object
* @member idviews
*/
idviews.idoverridegroup_spec = make_idoverridegroup_spec();
/**
* Register entity
* @member idviews
*/
idviews.register = function() {
var e = reg.entity;
var f = reg.facet;
var a = reg.action;
var w = reg.widget;
e.register({type: 'idview', spec: idviews.spec});
e.register({
type: 'idoverrideuser',
spec: idviews.idoverrideuser_spec,
pre_ops: [idviews.aduser_idoverrideuser_pre_op]
});
e.register({type: 'idoverridegroup', spec: idviews.idoverridegroup_spec});
f.copy('attribute', 'idview_appliedtohosts', {
factory: idviews.appliedtohosts_facet
});
a.register('idview_apply', idviews.apply_action);
a.register('idview_apply_hostgroups', idviews.apply_hostgroups_action);
a.register('idview_unapply', idviews.unapply_action);
a.register('idview_unapply_host', idviews.unapply_host_action);
a.register('idview_unapply_hostgroups', idviews.unapply_hostgroups_action);
w.register('idviews_certs', idviews.idviews_certs_widget);
w.register('cert_textarea', idviews.cert_textarea_widget);
};
phases.on('registration', idviews.register);
return idviews;
});

File diff suppressed because it is too large Load Diff

95
install/ui/src/freeipa/jquery.js vendored Normal file
View File

@@ -0,0 +1,95 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//
// AMD Wrapper for jQuery
//
define(function() {
$ = jQuery;
//
// Following code taken from jQuery UI library, MIT license, see
// README-LICENSES.txt
//
$.fn.extend({
focus: (function( orig ) {
return function( delay, fn ) {
return typeof delay === "number" ?
this.each(function() {
var elem = this;
window.setTimeout(function() {
$( elem ).focus();
if ( fn ) {
fn.call( elem );
}
}, delay );
}) :
orig.apply( this, arguments );
};
})( $.fn.focus )
});
// selectors
function focusable( element, isTabIndexNotNaN ) {
var map, mapName, img,
nodeName = element.nodeName.toLowerCase();
if ( "area" === nodeName ) {
map = element.parentNode;
mapName = map.name;
if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
return false;
}
img = $( "img[usemap=#" + mapName + "]" )[0];
return !!img && visible( img );
}
return ( /input|select|textarea|button|object/.test( nodeName ) ?
!element.disabled :
"a" === nodeName ?
element.href || isTabIndexNotNaN :
isTabIndexNotNaN) &&
// the element and all of its ancestors must be visible
visible( element );
}
function visible( element ) {
return $.expr.filters.visible( element ) &&
!$( element ).parents().addBack().filter(function() {
return $.css( this, "visibility" ) === "hidden";
}).length;
}
$.extend( $.expr[ ":" ], {
focusable: function( element ) {
return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
},
tabbable: function( element ) {
var tabIndex = $.attr( element, "tabindex" ),
isTabIndexNaN = isNaN( tabIndex );
return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
}
});
return $;
});

View File

@@ -0,0 +1,27 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//
// AMD Wrapper for json2 library
//
define(function() {
return JSON;
});

View File

@@ -0,0 +1,107 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/lang',
'./app_container',
'./ipa',
'exports' // for handling circular dependency
],
function(lang, app_container, IPA, exports) {
var get_menu = function() {
return app_container.app.menu;
},
/**
* Menu proxy.
*
* Exports public interface for dealing with menu items.
* @class menu
*/
/**
* Adds menu item.
* Takes a spec of menu item.
* Normalizes item's name, parent, adds children if specified
*
* @method add_item
* @param {navigation.MenuItem} item
* @param {string|navigation.MenuItem} parent
* @param {Object} options
*/
add_item = function(item, parent, options) {
var menu = get_menu();
return menu.add_item(item, parent, options);
},
/**
* Removes menu item
*
* @method remove_item
* @param {string|navigation.MenuItem} name or menu item to remove
*/
remove_item = function(item) {
var menu = get_menu();
return menu.items.remove(item);
},
/**
* Query internal data store by using default search options or supplied
* search options.
*
* @method query
* @param {Object} query
* @param {Object} [search_options] Search options, overrides default
* @return {QueryResult}
*/
query = function(query, search_options) {
var menu = get_menu();
if (search_options) {
return menu.items.query(query, search_options);
} else {
return menu.query(query);
}
},
/**
* Get current instance of menu
* @method get
* @return {navigation.Menu}
*/
get = function() {
return get_menu();
};
// Module export
exports = {
add_item: add_item,
remove_item: remove_item,
query: query,
get: get
};
return exports;
});

View File

@@ -0,0 +1,81 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/lang',
'./_base/Provider',
'./_base/Search_provider'
], function(lang, Provider, Search_provider) {
/**
* Metadata provider
*
* Contains multiple providers for specific metadata searches:
*
* - `@m:`: provider for whole metadata
* - `@mo:`: provider for objects (entities)
* - `@mc:`: provider for commands
* - `@mo-param:`: search provider for object params
* - `@mc-arg:`: search provider for command arguments
* - `@mc-opt:`: search provider for command options
*
* @class metadata
* @singleton
* @extends _base.Provider
*/
var metadata = new Provider({
code: '@m:'
});
var objects = new Provider({
code: '@mo:',
source: metadata,
path: 'objects'
});
var commands = new Provider({
code: '@mc:',
source: metadata,
path: 'commands'
});
var object_param = new Search_provider({
code: '@mo-param:',
source: metadata,
path: 'objects',
base_query: '%1.takes_params',
array_attr: 'name'
});
var cmd_arg = new Search_provider({
code: '@mc-arg:',
source: metadata,
path: 'commands',
base_query: '%1.takes_args',
array_attr: 'name'
});
var cmd_option = new Search_provider({
code: '@mc-opt:',
source: metadata,
path: 'commands',
base_query: '%1.takes_options',
array_attr: 'name'
});
metadata.providers.push(objects, commands, object_param, cmd_arg, cmd_option);
return metadata;
});

View File

@@ -0,0 +1,162 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/lang',
'./navigation/routing'
],
function(lang, routing) {
var navigation = {
/**
* Navigation tells application to show certain facet.
*
* It's proxy for navigation/Router instance in current running
* application.
*
* Modules just use the interface, they don't have to care about the logic in
* the background.
* @class navigation
*/
/**
* Sets property of params depending on arg type following way:
* for String sets params.facet
* for Facet sets params.facet (based on show function)
* for Object sets params.args
* for Array sets params.pkeys
* @ignore
* @param Object params
* @param {Object|facet.facet|string|Function} arg
*/
set_params: function(params, arg) {
if (lang.isArray(arg)) {
params.pkeys = arg;
} else if (typeof arg === 'object') {
if (typeof arg.show === 'function') params.facet = arg;
else params.args = arg;
} else if (typeof arg === 'string') {
params.facet = arg;
}
},
/**
* Show facet.
*
* Takes 3 arguments:
* * facet(String or Facet)
* * pkeys (Array)
* * args (Object)
*
* Argument order is not defined. They are recognized based on their
* type.
*
* When facet is defined as a string it has to be registered in
* facet register.
*
* When it's an object (Facet) and has an entity set it will be
* dealt as entity facet.
* @method show
* @param {Object|facet.facet|string|Function} arg1
* @param {Object|facet.facet|string|Function} arg2
* @param {Object|facet.facet|string|Function} arg3
*/
show: function(arg1, arg2, arg3) {
var params = {};
this.set_params(params, arg1);
this.set_params(params, arg2);
this.set_params(params, arg3);
var facet = params.facet;
if (typeof facet === 'string') {
return routing.navigate(['generic', facet, params.args]);
}
if (!facet) throw 'Argument exception: missing facet';
if (facet && facet.entity) {
return routing.navigate([
'entity',
facet.entity.name,
facet.name,
params.pkeys,
params.args]);
} else {
return routing.navigate(['generic', facet.name, params.args]);
}
},
/**
* Show entity facet
*
* arg1,arg2,arg3 are:
* facet name as String
* pkeys as Array
* args as Object
* @method show_entity
* @param String Enity name
* @param {Object|facet.facet|string|Function} arg1
* @param {Object|facet.facet|string|Function} arg2
* @param {Object|facet.facet|string|Function} arg3
*/
show_entity: function(entity_name, arg1, arg2, arg3) {
var params = {};
this.set_params(params, arg1);
this.set_params(params, arg2);
this.set_params(params, arg3);
return routing.navigate(['entity', entity_name, params.facet,
params.pkeys, params.args]);
},
/**
* Uses lower level access
*
* `experimental`
*
* Navigates to generic page by changing hash.
*
* @param {string} hash Hash of the change
* @param {Object} [facet] Facet we are navigating to. Usually used for
* notification purposes
*/
show_generic: function(hash, facet) {
routing.router.navigate_to_hash(hash, facet);
},
/**
* Show default facet
* @method show_default
*/
show_default: function() {
routing.navigate(routing.default_path);
},
create_hash: function(facet, option) {
return routing.create_hash(facet, option);
}
};
return navigation;
});

View File

@@ -0,0 +1,250 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/store/Memory',
'dojo/_base/array',
'dojo/_base/lang',
'dojo/store/Observable',
'dojo/Evented',
'../reg',
'../text'
], function(declare, Memory_store, array, lang, Observable, Evented, reg, text) {
return declare([Evented],
/**
* Menu store
*
* Maintains menu hierarchy and selection state.
*
* @class navigation.Menu
*
*/
{
/**
* Menu name
* @property {String}
*/
name: null,
/**
* Dojo Store of menu items
* @property {Store}
*/
items: null,
/**
* Delimiter used in name creation
* To avoid having multiple menu items with the same name.
* @property {String}
*/
path_delimiter: '/',
/**
* Selected menu items
* @property {Array}
*/
selected: [],
/**
* Default search options: sort by position
* @property {Object}
*/
search_options: { sort: [{attribute:'position'}]},
/**
* Takes a spec of menu item.
* Normalizes item's name, parent, adds children if specified
*
* @param {Object} item - spec
* @param {string/Object} parent - name or menu item
* @param {Object} options
*/
add_item: function(item, parent, options) {
item = lang.clone(item); //don't modify original spec
// each item must have a name and a label
// FIXME: consider to move entity and facet stuff outside of this object
if (!item.name) {
if (item.facet && item.entity) {
item.name = item.entity + '_' + item.facet;
} else {
item.name = item.facet || item.entity;
}
}
if (!item.name) {
window.console.error('Missing menu item property: \'name\'', item);
return false;
}
if (item.label) item.label = text.get(item.label);
if (item.title) item.title = text.get(item.title);
if (item.entity) {
var entity = reg.entity.get(item.entity);
if (!entity) {
return false; //quit
}
if (!item.label) item.label = entity.label;
if (!item.title) item.title = entity.title;
} else if (item.facet) {
var facet = reg.facet.get(item.facet);
if (!facet) {
return false; //quit
}
if (!item.label) item.label = facet.label;
if (!item.title) item.title = facet.title;
}
item.hidden = !!item.hidden;
item.selected = false;
// check parent
if (typeof parent === 'string') {
parent = this.items.get(parent);
if (!parent) throw 'Menu item\'s parent doesn\t exist';
} else if (typeof parent === 'object') {
if (!this.items.getIdentity(parent)) {
throw 'Supplied parent isn\'t menu item';
}
}
var parent_name = parent ? parent.name : null;
var siblings = this.items.query({ parent: parent_name });
if (!item.position) item.position = siblings.total;
// TODO: add reordering of siblings when position set
item.parent = parent_name;
if (parent) {
// names have to be unique
item.name = parent.name + this.path_delimiter + item.name;
}
// children will be added separately
var children = item.children;
delete item.children;
// finally add the item
try {
this.items.add(item);
} catch(e) {
window.console.error("Unable to add menu item", item);
throw e;
}
// add children
if (children) {
array.forEach(children, function(child) {
this.add_item(child, item);
}, this);
}
return true;
},
/**
* Add multiple items
* @param {Array} items - spec of items
*/
add_items: function(/* Array */ items) {
array.forEach(items, function(item) {
this.add_item(item);
}, this);
},
/**
* Query internal data store by using default search options.
*
* @param {Object} Query filter
* @return {QueryResult}
*/
query: function(query) {
return this.items.query(query, this.search_options);
},
/**
* Marks item and all its parents as selected.
* @private
*/
_select: function(item) {
item.selected = true;
this.selected.push(item);
this.items.put(item);
if (item.parent) {
var parent = this.items.get(item.parent);
parent.selected_child = item.name;
this._select(parent);
}
},
/**
* Selects a menu item and all it's ancestors.
* @param {string/navigation.MenuItem} item menu item to select
*/
select: function(item) {
if (typeof item == 'string') {
item = this.items.get(item);
}
// FIXME: consider to raise an exception
if (!item || !this.items.getIdentity(item)) return false;
// deselect previous
var old_selection = lang.clone(this.selected);
array.forEach(this.selected, function(mi) {
mi.selected = false;
this.items.put(mi);
}, this);
this.selected = [];
// select new
this._select(item);
var select_state = {
item: item,
new_selection: this.selected,
old_selection: old_selection
};
this.emit('selected', select_state);
return select_state;
},
/**
* @param {Object} spec - Specification object
* @param {Array} spec.items - Menu items
* @param {string} spec.name - Name
*/
constructor: function(spec) {
spec = spec || {};
this.items = new Observable( new Memory_store({
idProperty: 'name'
}));
spec = lang.clone(spec);
this.add_items(spec.items || []);
delete spec.items;
declare.safeMixin(this, spec);
}
}); //declare freeipa.menu
}); //define

View File

@@ -0,0 +1,98 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* This is a virtual object which serves only for documentation purposes. It
* describes what properties has the created menu item and what can be part
* of menu item object specification.
*
* Following properties are not in created in menu item:
*
* - children
*
* Following properties may be part of menu item at runtime:
*
* - selected
* - parent
* - selected_child
*
* @class navigation.MenuItem
* @abstract
*/
var MenuItem = {
/**
* Name - menu item identifier
*/
name: '',
/**
* Visible text
*/
label: '',
/**
* Title
*/
title: '',
/**
* Position for ordering
*/
position: 0,
/**
* Children
*
* - next navigation level
* @property {Array.<navigation.MenuItem>}
*/
children: null,
/**
* Entity name
*/
entity: '',
/**
* Facet name
*/
facet: '',
/**
* Control item visibility but can serve for other evaluations (nested entities)
*/
hidden: '',
/**
* Runtime property
* Should not be set by hand. Indicates whether item is selected.
*/
selected: false,
/**
* Parent menu item's name
*/
parent: null,
/**
* Some child is selectd. Runtime property.
*/
selected_child: null
};

View File

@@ -0,0 +1,164 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/Evented',
'dojo/router'
],
function(declare, Evented, router) {
/**
* Router
*
* This component keeps menu and routes in sync. It signalizes
* other components to display facet by sending 'show-facet' event.
* Other components can use navigate_to_* methods to change currently
* displayed facet. This change can be canceled in 'facet-change'
* event handler.
* @class navigation.Router
*/
var navigation = declare([Evented], {
/**
* Holds references to register route handlers.
* Can be used for unregistering routes.
* @property {Array.<Function>}
*/
route_handlers: [],
/**
* Prefix of all routes for this navigation. Useful for multiple
* navigation objects in one application.
* @property {string}
*/
route_prefix: '',
/**
* Used during facet changing. Set it to true in 'facet-change'
* event handler to stop the change.
* @property {boolean}
*/
canceled: false,
/**
* Flag to indicate that next hash change should not invoke showing a
* facet.
* Main purpose: updating hash.
* @property {boolean}
*/
ignore_next: false,
/**
* Register a route-handler pair to a dojo.router
* Handler will be run in context of this object
*
* @param {string|Array.<string>} route or routes to register
* @param {Function} handler to be associated with the route(s)
*/
register_route: function(route, handler) {
if (route instanceof Array) {
for (var i=0, l=route.length; i<l; i++) {
this.register_route(route[i], handler);
}
} else {
var r = this.route_prefix + route;
this.route_handlers.push(router.register(r, handler.bind(this)));
}
},
/**
* Navigate to given hash
*
* @fires facet-change
* @fires facet-change-canceled
*/
navigate_to_hash: function(hash, facet) {
this.canceled = false;
this.emit('facet-change', { facet: facet, hash: hash });
if (this.canceled) {
this.emit('facet-change-canceled', { facet: facet, hash : hash });
return false;
}
this.update_hash(hash, false);
return true;
},
/**
* Changes hash to supplied
*
* @param {string} Hash to set
* @param {boolean} Whether to suppress following hash change handler
*/
update_hash: function(hash, ignore_change) {
if (window.location.hash === "#" + hash) return;
this.ignore_next = !!ignore_change;
router.go(hash);
},
/**
* Returns and resets `ignore_next` property.
*/
check_clear_ignore: function() {
var ignore = this.ignore_next;
this.ignore_next = false;
return ignore;
},
/**
* Tells other component to show given facet.
*/
show_facet: function(facet) {
this.emit('facet-show', {
facet: facet
});
},
/**
* Raise 'error'
* @protected
* @fires error
*/
_error: function(msg, type, context) {
this.emit('error', {
message: msg,
type: type,
context: context
});
},
/**
* Starts routing
*/
startup: function() {
router.startup();
},
constructor: function(spec) {
spec = spec || {};
}
});
return navigation;
});

View File

@@ -0,0 +1,368 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([], function() {
/**
* Specification of menu
* @singleton
* @class navigation.menu_spec
*/
var nav = {};
/**
* Admin menu
*/
nav.admin = {
name: 'admin',
items: [
{
name: 'identity',
label: '@i18n:tabs.identity',
children: [
{
entity: 'user',
facet: 'search',
children: [
{
entity: 'stageuser',
facet: 'search',
hidden: true
},
{
entity: 'user',
facet: 'search_preserved',
hidden: true
}
]
},
{ entity: 'host' },
{ entity: 'service' },
{
entity: 'group',
label: '@i18n:objects.group.groups',
facet: 'search',
children: [
{
entity: 'hostgroup',
facet: 'search',
hidden: true
},
{
entity: 'netgroup',
facet: 'search',
hidden: true
}
]
},
{ entity: 'idview' },
{
name: 'automember',
label: '@i18n:tabs.automember',
children: [
{
name: 'amgroup',
entity: 'automember',
facet: 'searchgroup',
label: '@i18n:objects.automember.usergrouprules',
children: [
{
entity: 'automember',
facet: 'usergrouprule',
hidden: true
}
]
},
{
name: 'amhostgroup',
entity: 'automember',
facet: 'searchhostgroup',
label: '@i18n:objects.automember.hostgrouprules',
children: [
{
entity: 'automember',
facet: 'hostgrouprule',
hidden: true
}
]
}
]
}
]
},
{
name: 'policy',
label: '@i18n:tabs.policy',
children: [
{
name: 'hbac',
label: '@i18n:tabs.hbac',
children: [
{ entity: 'hbacrule' },
{ entity: 'hbacsvc' },
{ entity: 'hbacsvcgroup' },
{ entity: 'hbactest' }
]
},
{
name: 'sudo',
label: '@i18n:tabs.sudo',
children: [
{ entity: 'sudorule' },
{ entity: 'sudocmd' },
{ entity: 'sudocmdgroup' }
]
},
{ entity: 'selinuxusermap' },
{ entity: 'pwpolicy' },
{ entity: 'krbtpolicy' }
]
},
{
name: 'authentication',
label: '@i18n:tabs.authentication',
children: [
{
entity: 'cert',
facet: 'search',
label: '@i18n:tabs.cert',
children: [
{
entity: 'certprofile',
facet: 'search',
hidden: true
},
{
entity: 'cert',
facet: 'search',
hidden: true
},
{
entity: 'caacl',
facet: 'search',
hidden: true
},
{
entity: 'ca',
facet: 'search',
hidden: true
}
]
},
{ entity: 'otptoken' },
{ entity: 'radiusproxy' },
{
entity: 'certmaprule',
facet: 'search',
children: [
{
entity: 'certmaprule',
facet: 'search'
},
{
entity: 'certmapconfig',
facet: 'details'
},
{
label: '@i18n:objects.certmap_match.facet_label',
entity: 'certmap_match'
}
]
}
]
},
{
name: 'network_services',
label: '@i18n:tabs.network_services',
children: [
{
name:'automount',
label: '@i18n:tabs.automount',
entity: 'automountlocation',
children: [
{ entity: 'automountlocation', hidden: true },
{ entity: 'automountmap', hidden: true },
{ entity: 'automountkey', hidden: true }
]
},
{
name:'dns',
label: '@i18n:tabs.dns',
children: [
{
entity: 'dnszone',
children: [
{ entity: 'dnsrecord', hidden: true }
]
},
{ entity: 'dnsforwardzone' },
{ entity: 'dnsserver' },
{ entity: 'dnsconfig' }
]
},
{
name: 'vault',
entity: 'vault',
facet: 'search',
children: [
{
entity: 'vault',
facet: 'user_search',
hidden: true
},
{
entity: 'vault',
facet: 'service_search',
hidden: true
},
{
entity: 'vault',
facet: 'shared_search',
hidden: true
},
{
entity: 'vaultconfig',
hidden: true
}
]
}
]
},
{
name: 'ipaserver',
label: '@i18n:tabs.ipaserver',
children: [
{
name: 'rbac',
label: '@i18n:tabs.role',
children: [
{ entity: 'role' },
{ entity: 'privilege' },
{ entity: 'permission' },
{ entity: 'selfservice' },
{ entity: 'delegation' }
]
},
{ entity: 'idrange' },
{ entity: 'realmdomains' },
{
name: 'trusts',
label: '@i18n:tabs.trust',
children: [
{ entity: 'trust' },
{ entity: 'trustconfig' }
]
},
{
entity: 'server',
label: '@i18n:tabs.topology',
facet: 'search',
children: [
{
entity: 'topologysuffix',
facet: 'search',
hidden: true
},
{
entity: 'server',
facet: 'search',
hidden: true
},
{
entity: 'server_role',
facet: 'search',
hidden: true
},
{
entity: 'domainlevel',
facet: 'details',
hidden: true
},
{
entity: 'location',
facet: 'search',
hidden: true
},
{
facet: 'topology-graph',
hidden: true
}
]
},
{
name: 'apibrowser',
label: '@i18n:widget.api_browser',
facet: 'apibrowser',
args: { 'type': 'command' }
},
{ entity: 'config' }
]
}
]
};
/**
* Self-service menu
*/
nav.self_service = {
name: 'self-service',
items: [
{ entity: 'user' },
{ entity: 'otptoken' },
{
name: 'vault',
entity: 'vault',
facet: 'search',
children: [
{
entity: 'vault',
facet: 'user_search',
hidden: true
},
{
entity: 'vault',
facet: 'service_search',
hidden: true
},
{
entity: 'vault',
facet: 'shared_search',
hidden: true
},
{
entity: 'vaultconfig',
hidden: true
}
]
}
]
};
nav.ad_self_service = {
name: 'ad_self_service',
items: [
{
entity: 'idoverrideuser',
label: 'Profile'
}
]
};
return nav;
});

View File

@@ -0,0 +1,505 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2014 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/declare',
'dojo/_base/lang',
'dojo/_base/array',
'dojo/io-query',
'../reg',
'../util'
],
function(declare, lang, array, ioquery, reg, util) {
/**
* Routing mechanism
* @class navigation.routing
* @singleton
*/
var routing = {
/**
* Router instance
* @property {navigation.Router}
*/
router: null,
/**
* Map of router handlers
* @property {Object}
*/
route_handlers: {},
/**
* Map of hash creators
* @property {Object}
*/
hash_creators: {},
/**
* Facet name to hash creator map
*
* - Key: facet name
* - Value: hash creator
*
* @type {Object}
*/
hc_facet_map: {},
/**
* Hash creator priority queue
*
* First item == highest priority
*
* @type {Array}
*/
hc_queue: [],
/**
* Map of navigators
* @type {Object}
*/
navigators: {},
/**
* Add hash creator at the beginning of hash creator queue
* @param {navigation.routing.HashCreator} hash_creator
* @param {Number} [position]
*/
add_hash_creator: function(hash_creator, position) {
if (position !== undefined) {
this.hc_queue.splice(position, 0, hash_creator);
} else {
this.hc_queue.unshift(hash_creator);
}
},
/**
* Add hash creator to hash creator map
* @param {string} facet_name
* @param {navigation.routing.HashCreator} hash_creator
*/
assign_hash_creator: function (facet_name, hash_creator) {
this.hc_facet_map[facet_name] = hash_creator;
},
/**
* Get hash creator for given facet
*
* Lookup priority:
*
* - facet -> hash creator map
* - hash creator queue
*
* @param {facets.Facet} facet [description]
* @return {navigation.routing.HashCreator}
*/
get_hash_creator: function(facet) {
var name = facet.name;
var hc = this.hc_facet_map[name];
if (!hc) {
for (var i=0, l=this.hc_queue.length; i<l; i++) {
if (this.hc_queue[i].handles(facet)) {
hc = this.hc_queue[i];
break;
}
}
}
return hc || null;
},
/**
* Create hash for given facet
*
* @param {facets.Facet} facet
* @param {Object|null} options
* @return {string} hash
*/
create_hash: function(facet, options) {
var hc = this.get_hash_creator(facet);
if (!hc) return '';
return hc.create_hash(this.router, facet, options);
},
/**
* Navigate by a Navigator
*
* Expects path as argument. Path is an array where
* first element is name of the Navigator, rest are
* navigators params.
*
* @param {Array} path
* @return {boolean}
*/
navigate: function(path) {
path = path.slice(0);
var nav_name = path.shift();
var nav = this.get_navigator(nav_name);
return nav.navigate.apply(nav, path);
},
/**
* Navigate to specific facet with give options
* @param {facets.Facet} facet
* @param {Object} options Options for hash creator
* @return {boolean}
*/
navigate_to_facet: function(facet, options) {
var hash = this.create_hash(facet, options);
return this.router.navigate_to_hash(hash, facet);
},
update_hash: function(facet, options) {
var hash = this.create_hash(facet, options);
this.router.update_hash(hash, true);
},
/**
* Add route handler to router
* @param {string|string[]} route Route or routes.
* @param {navigation.routing.RouteHandler} handler Handler
*/
add_route: function(route, handler) {
this.route_handlers[handler.name] = handler;
this.router.register_route(route, handler.get_handler());
},
/**
* Add navigator
* @param {navigation.routing.Navigator} navigator
*/
add_navigator: function(navigator) {
this.navigators[navigator.name] = navigator;
},
/**
* Get navigator by name
* @param {string} name Navigator's name
* @return {navigation.routing.Navigator}
*/
get_navigator: function(name) {
return this.navigators[name];
},
/**
* Path for default facet
* @type {Array}
*/
default_path: ['entity', 'user', 'search'],
/**
* Variations of entity routes
* @property {string[]}
*/
entity_routes: [
'/e/:entity/:facet/:pkeys/*args',
'/e/:entity/:facet//*args',
'/e/:entity/:facet/:pkeys',
'/e/:entity/:facet',
'/e/:entity'
],
/**
* Variations of simple page routes
* @property {string[]}
*/
page_routes: [
'/p/:page/*args',
'/p/:page'
]
};
/**
* General route handler
*
* @class navigation.routing.RouteHandler
*/
routing.RouteHandler = declare([], {
handler: null,
name: 'generic',
/**
* Handle router event
* @param {Object} event
* @param {navigation.Router} router
*/
handle: function (event, router) {
if (router.check_clear_ignore()) return;
var facet_name = event.params.page;
var args;
try {
args = ioquery.queryToObject(event.params.args || '');
} catch (e) {
router._error('URI error', 'route', event.params);
return;
}
// set new facet state
var facet = reg.facet.get(facet_name);
if (!facet) {
router._error('Unknown facet', 'route', event.params);
return;
}
facet.reset_state(args);
router.show_facet(facet);
},
/**
* Create handler callback for router
* @return {Function} callback
*/
get_handler: function() {
if (!this.handler) {
var self = this;
this.handler = function(event) {
self.handle(event, this);
};
}
return this.handler;
}
});
/**
* Entity route handler
*
* @class navigation.routing.EntityRouteHandler
* @extends {navigation.routing.RouteHandler}
*/
routing.EntityRouteHandler = declare([routing.RouteHandler], {
name: 'entity',
/**
* @inheritDoc
*/
handle: function (event, router) {
if (router.check_clear_ignore()) return;
var entity_name = event.params.entity;
var facet_name = event.params.facet;
var pkeys, args;
try {
pkeys = this._decode_pkeys(event.params.pkeys || '');
args = ioquery.queryToObject(event.params.args || '');
} catch (e) {
router._error('URI error', 'route', event.params);
return;
}
args.pkeys = pkeys;
// set new facet state
var entity = reg.entity.get(entity_name);
if (!entity) {
router._error('Unknown entity', 'route', event.params);
return;
}
var facet = entity.get_facet(facet_name);
if (!facet) {
router._error('Unknown facet', 'route', event.params);
return;
}
facet.reset_state(args);
router.show_facet(facet);
},
/**
* Splits strings by '&' and return an array of URI decoded parts.
* Example: 'foo%20&bar' => ['foo ', 'bar']
*/
_decode_pkeys: function(str) {
if (!str) return [];
var keys = str.split('&');
for (var i=0; i<keys.length; i++) {
keys[i] = decodeURIComponent(keys[i]);
}
return keys;
}
});
/**
* Hash creator creates a hash string from given facet and options
*
* This is default hash creator for generic facets.
*
* @class navigation.routing.HashCreator
*/
routing.HashCreator = declare([], {
prefix: 'p',
name: 'generic',
create_hash: function(router, facet, options) {
var path = [router.route_prefix, this.prefix, facet.name];
var args = ioquery.objectToQuery(options || {});
if (!util.is_empty(args)) path.push(args);
var hash = path.join('/');
return hash;
},
handles: function(facet) {
return true;
}
});
/**
* Hash creator for entity facets
* @class navigation.routing.EntityHashCreator
* @extends navigation.routing.HashCreator
*/
routing.EntityHashCreator = declare([routing.HashCreator], {
prefix: 'e',
name: 'entity',
create_hash: function(router, facet, options) {
options = lang.clone(options);
var entity_name = facet.entity.name;
var pkeys = this._encode_pkeys(options.pkeys || []);
delete options.pkeys;
var args = ioquery.objectToQuery(options || {});
var path = [router.route_prefix, this.prefix, entity_name, facet.name];
if (!util.is_empty(args)) path.push(pkeys, args);
else if (!util.is_empty(pkeys)) path.push(pkeys);
var hash = path.join('/');
return hash;
},
handles: function(facet) {
return !!facet.entity;
},
/**
* URI Encodes array items and delimits them by '&'
* Example: ['foo ', 'bar'] => 'foo%20&bar'
*/
_encode_pkeys: function(pkeys) {
var ret = [];
array.forEach(pkeys, function(pkey) {
ret.push(encodeURIComponent(pkey));
});
return ret.join('&');
}
});
/**
* Navigate to other facet.
*
* @class navigation.routing.Navigator
*/
routing.Navigator = declare([], {
name: 'generic',
navigate: function(facet_name, args) {
var facet = reg.facet.get(facet_name);
if (!facet) {
routing.router._error('Unknown facet', 'navigation', { facet: facet_name});
return false;
}
if (!args) args = facet.get_state();
return routing.navigate_to_facet(facet, args);
}
});
/**
* Used for switching to entities' facets. Current target facet
* state is used as params (pkeys, args) when none of pkeys and args
* are used (useful for switching to previous page with keeping the context).
*
* @class navigation.routing.EntityNavigator
* @extends navigation.routing.Navigator
*/
routing.EntityNavigator = declare([routing.Navigator], {
name: 'entity',
navigate: function(entity_name, facet_name, pkeys, args) {
var entity = reg.entity.get(entity_name);
if (!entity) {
routing.router._error('Unknown entity', 'navigation', { entity: entity_name});
return false;
}
var facet = entity.get_facet(facet_name);
if (!facet) {
routing.router._error('Unknown facet', 'navigation', { facet: facet_name});
return false;
}
// Use current state if none supplied
if (!pkeys && !args) {
args = facet.get_state();
}
args = args || {};
// Facets may be nested and require more pkeys than supplied.
args.pkeys = facet.get_pkeys(pkeys);
return routing.navigate_to_facet(facet, args);
}
});
/**
* Init routing
*
* Sets default routes, handlers, hash creators and navigators
*
* @param {navigation.Router} router
*/
routing.init = function(router) {
if (router) this.router = router;
var generic_hc = new routing.HashCreator();
var entity_hc = new routing.EntityHashCreator();
var generic_rh = new routing.RouteHandler();
var entity_rh = new routing.EntityRouteHandler();
var generic_n = new routing.Navigator();
var entity_n = new routing.EntityNavigator();
this.add_hash_creator(generic_hc);
this.add_hash_creator(entity_hc);
this.add_route(this.page_routes, generic_rh);
this.add_route(this.entity_routes, entity_rh);
this.add_navigator(generic_n);
this.add_navigator(entity_n);
};
return routing;
});

View File

@@ -0,0 +1,399 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['./ipa', './jquery'], function(IPA, $) {
var NET = {};
NET.ip_address = function(spec) {
spec = spec || {};
if (typeof spec === 'string') {
spec = {
address: spec
};
}
var that = IPA.object();
that.input = spec.address;
that.type = spec.type;
that.parts = spec.parts;
that.reverse_address = '';
that.only_decimal = spec.only_decimal !== undefined? spec.only_decimal :
false; //for parsing IPv4 address
that.parse = function() {
if (!that.input && !that.parts) {
that.set_error('no input');
return false;
}
if (!that.type) {
that.type = that.detect_type();
}
if (that.type === 'v4-quads') {
return that.parse_v4_quads();
} else if (that.type === 'v4-int') {
return that.parse_v4_int();
} else if (that.type === 'v6') {
return that.parse_v6();
}
that.set_error('not an ip address');
return false;
};
that.detect_type = function() {
var type;
if (!that.input) return null;
if (that.input.indexOf(':') > -1) type = 'v6';
else if (that.input.indexOf('.') > -1) type = 'v4-quads';
else type = 'v4-int';
return type;
};
that.parse_v4_int = function() {
var part = { value: that.input };
if(!that.is_part_valid_v4(part, 32, that.only_decimal)) return false;
that.parts = [];
that.make_quads(part.decimal_value, that.parts);
that.valid = true;
return true;
};
that.parse_v4_quads = function() {
if (!that.parts) {
that.parts = that.input.split('.');
}
if (that.parts.length !== 4) {
return that.set_error('invalid number of parts');
}
for (var i=0; i<4; i++) {
var part = { value: that.parts[i] };
if (!that.is_part_valid_v4(part, 8, that.only_decimal)) {
return false;
}
that.parts[i] = part.decimal_value.toString(10);
}
that.valid = true;
return true;
};
that.parse_v6 = function() {
if (!that.parts) {
that.parts = that.input.split(':');
}
var total_parts = that.parts.length;
var ipv4_present = false;
var double_colon = false;
var double_colon_position;
var i;
//usecases like ':'
if (that.parts.length <= 2) {
return that.set_error('invalid format');
}
for (i=0; i<that.parts.length; i++) {
var part = that.parts[i];
if (i === that.parts.length -1 && part.indexOf('.') > -1) {
ipv4_present = true;
total_parts++; //ipv4 part consists of 4 octects (two parts)
}
//checking for ::
if (part.length === 0) {
if (!double_colon || //first occurance
(double_colon && i === 1) || //still at the beginning
(double_colon && i === that.parts.length - 1 &&
double_colon_position === i -1)) { //still at the end
part = '0000';
that.parts[i] = part;
double_colon = true;
double_colon_position = i;
} else { //second occurance of ::
return that.set_error('invalid format: mupltiple ::');
}
}
//add missing zeros for not empty parts
if (part.length !== 0 && part.length < 4) {
part = add_leading_zeros(part, 4 - part.length);
that.parts[i] = part;
}
}
//add missing empty parts
if (double_colon) {
var parts_to_add = 8 - total_parts;
for (i=0; i<parts_to_add; i++) {
that.parts.splice(double_colon_position, 0, '0000');
}
}
//change ipv4 part
if (ipv4_present) {
var ipv4_address = NET.ip_address();
ipv4_address.input = that.parts[that.parts.length -1];
ipv4_address.only_decimal = true;
if (ipv4_address.parse() && ipv4_address.type === 'v4-quads') {
var v4_parts = ipv4_address.parts;
var oct1 = dec_2_hex(v4_parts[0]);
var oct2 = dec_2_hex(v4_parts[1]);
var oct3 = dec_2_hex(v4_parts[2]);
var oct4 = dec_2_hex(v4_parts[3]);
//replace IPv4 part with two IPv6 parts (4 octets)
that.parts[that.parts.length -1] = oct1+oct2;
that.parts.push(oct3+oct4);
} else {
return that.set_error('invalid IPv4 part');
}
}
//validate length after modifications
if (that.parts.length !== 8) {
return that.set_error('invalid number of parts');
}
//validate each part
for (i=0; i<8; i++) {
if (!that.is_part_valid_v6(that.parts[i])) {
return false;
}
}
that.valid = true;
return true;
};
function dec_2_hex(val) {
var dec = parseInt(val, 10);
var hex = dec.toString(16);
hex = add_leading_zeros(hex, 2 - hex.length);
return hex;
}
function add_leading_zeros(val, num) {
for (var i=0; i<num; i++) {
val='0'+val;
}
return val;
}
that.get_reverse = function() {
if (!that.valid) return 'invalid input address';
if (that.type === 'v4-quads' || that.type === 'v4-int') {
return that.get_v4_reverse();
} else if (that.type === 'v6') {
return that.get_v6_reverse();
}
return '';
};
that.get_v4_reverse = function() {
that.reverse_parts = [];
for (var i=3; i>=0; i--) {
that.reverse_parts.push(that.parts[i]);
}
that.reverse_parts.push('in-addr');
that.reverse_parts.push('arpa');
return that.reverse_parts.join('.');
};
that.get_v6_reverse = function() {
that.reverse_parts = [];
var address = that.parts.join('');
for (var i=31; i>=0; i--) {
that.reverse_parts.push(address[i]);
}
that.reverse_parts.push('ip6');
that.reverse_parts.push('arpa');
return that.reverse_parts.join('.');
};
that.set_error = function(msg) {
that.valid = false;
that.error = msg;
return false;
};
that.is_part_valid_v6 = function(str) {
if (str.length === 0) {
return that.set_error('not a number');
}
if (str.length > 4) {
return that.set_error('wrong format - too long');
}
for (var i=0; i<str.length; i++) {
var digit = parseInt(str[i], 16);
//check if character is digit
if (isNaN(digit)) {
return that.set_error('invalid format: \''+digit+'\'');
}
}
return true;
};
/*
* Checks if part.value is valid IPv4 integer of given size (in bits).
* Validation can be limited only to decimal values by only_decimal argument.
* Sets its decimal representation to part.decimal_value.
*/
that.is_part_valid_v4 = function(part, bits, only_decimal) {
if (!part.value || part.value.length === 0) {
return that.set_error('not a number');
}
var radix = that.get_radix(part.value);
var number = part.value;
if (radix === 16) number = part.value.substring(2);
else if (radix === 8) number = part.value.substring(1);
if (radix !== 10 && only_decimal) {
return that.set_error('not a decimal number');
}
for (var i=0; i<number.length; i++) {
var digit = parseInt(number[i], radix);
//check if character is digit in its radix
if (isNaN(digit)) {
return that.set_error('invalid format: \''+digit+'\'');
}
//check for leading zeros
if (i === 0 && digit === 0 && number.length > 1) {
return that.set_error('invalid format: leading zeros');
}
}
var max_value = Math.pow(2, bits) - 1;
part.decimal_value = parseInt(part.value, radix);
if (part.decimal_value > max_value) {
return that.set_error('value out of range');
}
return true;
};
that.get_radix = function(str) {
var normalized = str.toLowerCase();
if (normalized.length > 2 &&
normalized[0] === '0' &&
normalized[1] === 'x') {
return 16;
} else if (normalized.length > 1 && normalized[0] === '0') {
return 8;
}
return 10;
};
that.make_quads = function(integer, quads) {
var hex_str = integer.toString(16);
if (hex_str.length < 8) {
hex_str = add_leading_zeros(hex_str, 8 - hex_str.length);
}
for (var i=0; i<hex_str.length; i+=2) {
var quad_hex = hex_str.substring(i,i+2);
var quad = parseInt(quad_hex, 16);
quads.push(quad.toString(10));
}
};
that.get_radix = function(str) {
var normalized = str.toLowerCase();
if (normalized.length > 2 &&
normalized[0] === '0' &&
normalized[1] === 'x') {
return 16;
} else if (normalized.length > 1 && normalized[0] === '0') {
return 8;
}
return 10;
};
that.parse();
return that;
};
return NET;
});

View File

@@ -0,0 +1,335 @@
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./phases',
'./reg',
'./association',
'./entity',
'./details',
'./rule',
'./search'
],
function(IPA, $, phases, reg) {
var exp = IPA.netgroup = {
remove_method_priority: IPA.config.default_priority - 1,
enable_priority: IPA.config.default_priority + 1
};
var make_spec = function() {
var spec = {
name: 'netgroup',
facet_groups: ['settings', 'member', 'memberof'],
facets: [
{
$type: 'search',
tab_label: '@i18n:objects.netgroup.netgroups',
facet_groups: [IPA.group.search_facet_group],
tabs_in_sidebar: true,
disable_facet_tabs: false,
columns: [
'cn',
'description'
]
},
{
$type: 'details',
$factory: IPA.netgroup.details_facet,
command_mode: 'info'
},
{
$type: 'association',
name: 'memberof_netgroup',
associator: IPA.serial_associator
}
],
standard_association_facets: true,
adder_dialog: {
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
};
add_netgroup_details_facet_widgets(spec.facets[1]);
return spec;
};
/**
* @ignore
* @param {Object} facet spec
*/
var add_netgroup_details_facet_widgets = function (spec) {
//
// Identity
//
spec.fields = [
{
name: 'cn',
widget: 'identity.cn'
},
{
$type: 'textarea',
name: 'description',
widget: 'identity.description'
},
{
name: 'nisdomainname',
widget: 'identity.nisdomainname'
}
];
spec.widgets = [
{
$type: 'details_section',
name: 'identity',
label: '@i18n:details.general',
widgets: [
{
name: 'cn'
},
{
$type: 'textarea',
name: 'description'
},
{
name: 'nisdomainname',
widget: 'general.nisdomainname'
}
]
}
];
//
// Users
//
spec.fields.push(
{
$type: 'radio',
name: 'usercategory',
widget: 'user.rule.usercategory'
},
{
$type: 'rule_association_table',
name: 'memberuser_user',
widget: 'user.rule.memberuser_user',
priority: IPA.netgroup.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberuser_group',
widget: 'user.rule.memberuser_group',
priority: IPA.netgroup.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'user',
label: '@i18n:objects.netgroup.user',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'rule',
radio_name: 'usercategory',
options: [
{ value: 'all',
label: '@i18n:objects.netgroup.anyone' },
{ value: '',
label: '@i18n:objects.netgroup.specified_users' }
],
tables: [
{ name: 'memberuser_user' },
{ name: 'memberuser_group' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'netgroup-memberuser_user',
name: 'memberuser_user',
add_method: 'add_member',
remove_method: 'remove_member',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member',
columns: [
{
name: 'memberuser_user',
label: '@i18n:objects.netgroup.users',
link: true
}
]
},
{
$type: 'rule_association_table',
id: 'netgroup-memberuser_group',
name: 'memberuser_group',
add_method: 'add_member',
remove_method: 'remove_member',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member',
columns: [
{
name: 'memberuser_group',
label: '@i18n:objects.netgroup.usergroups',
link: true
}
]
}
]
}
]
}
);
//
// Hosts
//
spec.fields.push(
{
$type: 'radio',
name: 'hostcategory',
widget: 'host.rule.hostcategory'
},
{
$type: 'rule_association_table',
name: 'memberhost_host',
widget: 'host.rule.memberhost_host',
priority: IPA.netgroup.remove_method_priority,
external: 'externalhost'
},
{
$type: 'rule_association_table',
name: 'memberhost_hostgroup',
widget: 'host.rule.memberhost_hostgroup',
priority: IPA.netgroup.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'host',
label: '@i18n:objects.netgroup.host',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'rule',
radio_name: 'hostcategory',
options: [
{
'value': 'all',
label: '@i18n:objects.netgroup.any_host'
},
{
'value': '',
label: '@i18n:objects.netgroup.specified_hosts'
}
],
tables: [
{ 'name': 'memberhost_host' },
{ 'name': 'memberhost_hostgroup' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'netgroup-memberhost_host',
name: 'memberhost_host',
add_method: 'add_member',
remove_method: 'remove_member',
external: 'externalhost',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member',
columns: [
{
name: 'memberhost_host',
label: '@i18n:objects.netgroup.hosts',
link: true
},
{
name: 'externalhost',
label: '@i18n:objects.netgroup.external',
formatter: 'boolean',
width: '200px'
}
]
},
{
$type: 'rule_association_table',
id: 'netgroup-memberhost_hostgroup',
name: 'memberhost_hostgroup',
add_method: 'add_member',
remove_method: 'remove_member',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member',
columns: [
{
name: 'memberhost_hostgroup',
label: '@i18n:objects.netgroup.hostgroups',
link: true
}
]
}
]
}
]
}
);
};
IPA.netgroup.details_facet = function(spec) {
var that = IPA.details_facet(spec);
that.update_on_success = function(data, text_status, xhr) {
that.refresh();
that.on_update.notify();
that.nofify_update_success();
};
that.update_on_error = function(xhr, text_status, error_thrown) {
that.refresh();
};
return that;
};
exp.entity_spec = make_spec();
exp.register = function() {
var e = reg.entity;
e.register({type: 'netgroup', spec: exp.entity_spec});
};
phases.on('registration', exp.register);
return exp;
});

View File

@@ -0,0 +1,30 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./jquery'
], function($) {
/**
* Wrapper for jquery.ordered_map
* @class ordered_map
*/
return $.ordered_map;
});

View File

@@ -0,0 +1,568 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/on',
'./ipa',
'./jquery',
'./menu',
'./phases',
'./reg',
'./details',
'./facet',
'./qrcode',
'./text',
'./search',
'./entity'],
function(on, IPA, $, menu, phases, reg, mod_details, mod_facet, QRCode, text) {
/**
* OTP tokens module
* @class
* @singleton
*/
var otptoken = IPA.otptoken = {
app_link: 'https://fedorahosted.org/freeotp/',
app_link_text: '@i18n:objects.otptoken.app_link'
};
var make_spec = function() {
return {
name: 'otptoken',
enable_test: function() {
return true;
},
facets: [
{
$type: 'search',
$pre_ops: [
// redefining 'add' and 'remove' actions to be shown in
// self service
{
$replace: [ [ 'actions', [
[
'add',
{
$type:'add',
name: 'add',
hide_cond: []
}
],
[
'batch_remove',
{
$type: 'batch_remove',
name: 'remove',
hide_cond: []
}
]
] ] ]
}
],
actions: [
{
$type: 'batch_items',
name: 'enable',
method: 'mod',
options: { ipatokendisabled: false },
needs_confirm: true,
enable_cond: ['item-selected'],
enabled: false,
success_msg: '@i18n:search.enabled',
confirm_msg: '@i18n:search.enable_confirm'
},
{
$type: 'batch_items',
name: 'disable',
method: 'mod',
options: { ipatokendisabled: true },
needs_confirm: true,
enable_cond: ['item-selected'],
enabled: false,
success_msg: '@i18n:search.disabled',
confirm_msg: '@i18n:search.disable_confirm'
},
'delete'
],
control_buttons: [
{
name: 'disable',
label: '@i18n:buttons.disable',
icon: 'fa-minus'
},
{
name: 'enable',
label: '@i18n:buttons.enable',
icon: 'fa-check'
}
],
columns: [
'ipatokenuniqueid',
'ipatokenowner',
{
name: 'ipatokendisabled',
label: '@i18n:status.label',
formatter: {
$type: 'boolean_status',
invert_value: true,
empty_value: false
}
},
'description'
]
},
{
$type: 'details',
actions: [
'select',
{
$type: 'object',
name: 'otp_enable',
label: '@i18n:objects.otptoken.enable',
method: 'mod',
needs_confirm: true,
confirm_msg: '@i18n:actions.enable_confirm',
options: { ipatokendisabled: false },
enable_cond: ['disabled'],
hide_cond: ['self-service']
},
{
$type: 'object',
name: 'otp_disable',
label: '@i18n:objects.otptoken.disable',
method: 'mod',
needs_confirm: true,
confirm_msg: '@i18n:actions.disable_confirm',
options: { ipatokendisabled: true },
enable_cond: ['enabled'],
hide_cond: ['self-service']
},
'delete'
],
header_actions: ['otp_enable', 'otp_disable', 'delete'],
state: {
evaluators: [
{
$factory: mod_details.enable_state_evaluator,
field: 'ipatokendisabled',
parser: {
$factory: IPA.boolean_formatter,
invert_value: true,
empty_value: false
}
},
mod_facet.self_service_state_evaluator
],
summary_conditions: [
mod_details.enabled_summary_cond,
mod_details.disabled_summary_cond
]
},
sections: [
{
name: 'details',
label: '@i18n:objects.otptoken.details',
fields: [
'ipatokenuniqueid',
'type',
{
$type: 'textarea',
name: 'description'
},
{
$type: 'entity_select',
name: 'ipatokenowner',
other_entity: 'user',
other_field: 'uid'
},
{
$type: 'datetime',
name: 'ipatokennotbefore'
},
{
$type: 'datetime',
name: 'ipatokennotafter'
},
'ipatokenvendor',
'ipatokenmodel',
'ipatokenserial',
'ipatokenotpalgorithm',
'ipatokenotpdigits',
{
name: 'ipatokentotpclockoffset',
measurement_unit: 'seconds',
hidden_if_empty: true
},
{
name: 'ipatokentotptimestep',
measurement_unit: 'seconds',
hidden_if_empty: true
},
{
name: 'ipatokenhotpcounter',
hidden_if_empty: true
}
]
}
]
},
{
$type: 'association',
name: 'managedby_user',
add_method: 'add_managedby',
remove_method: 'remove_managedby'
}
],
adder_dialog: {
$factory: otptoken.adder_dialog,
$pre_ops: [
otptoken.adder_dialog_preop
],
$post_ops: [
otptoken.adder_dialog_qrcode_post_op
],
policies: [
{ $factory: otptoken.adder_policy }
],
fields: [
{
$type: 'radio',
name: 'type',
default_value: 'totp',
options: [
{ label: '@i18n:objects.otptoken.type_totp', value: 'totp' },
{ label: '@i18n:objects.otptoken.type_hotp', value: 'hotp' }
]
},
{
name: 'ipatokenuniqueid',
required: false
},
'description',
{// only when not self-service
$type: 'entity_select',
name: 'ipatokenowner',
other_entity: 'user',
other_field: 'uid'
},
{
$type: 'datetime',
name: 'ipatokennotbefore'
},
{
$type: 'datetime',
name: 'ipatokennotafter'
},
'ipatokenvendor',
'ipatokenmodel',
'ipatokenserial',
'ipatokenotpkey',
{
$type: 'radio',
name: 'ipatokenotpalgorithm',
default_value: 'sha1',
options: [
'sha1', 'sha256', 'sha384', 'sha512'
]
},
{
$type: 'radio',
name: 'ipatokenotpdigits',
default_value: '6',
options: ['6', '8']
},
{
name: 'ipatokentotptimestep',
measurement_unit: 'seconds'
}
],
selfservice_fields: [
{
$type: 'radio',
name: 'type',
default_value: 'totp',
options: [
{ label: '@i18n:objects.otptoken.type_totp', value: 'totp' },
{ label: '@i18n:objects.otptoken.type_hotp', value: 'hotp' }
]
},
'description'
]
}
};};
otptoken.adder_policy = function(spec) {
var that = IPA.facet_policy(spec);
that.init = function() {
var type_f = that.container.fields.get_field('type');
on(type_f, 'value-change', that.on_type_change);
};
that.on_type_change = function(args) {
var step_f = that.container.fields.get_field('ipatokentotptimestep');
if (!step_f) return;
var step_w = step_f.widget;
var is_totp = args.value[0] === 'totp';
step_f.set_enabled(is_totp);
step_w.set_visible(is_totp);
};
return that;
};
/**
* OTP adder dialog pre-op.
*
* Switches fields to different set when in self-service.
*/
otptoken.adder_dialog_preop = function(spec) {
spec.self_service = IPA.is_selfservice;
if (IPA.is_selfservice) {
spec.fields = spec.selfservice_fields;
}
return spec;
};
/**
* OTP adder dialog
*
* @class
* @extends IPA.entity_adder_dialog
*/
otptoken.adder_dialog = function(spec) {
var that = IPA.entity_adder_dialog(spec);
/**
* Dialog sends different command options when in self-service mode.
*/
that.self_service = !!spec.self_service;
/** @inheritDoc */
that.create_add_command = function(record) {
var command = that.entity_adder_dialog_create_add_command(record);
if (that.self_service) {
command.set_option('ipatokenowner', IPA.whoami.data.uid[0]);
}
return command;
};
return that;
};
/**
* Displays text as QR code
* @class
* @extends IPA.widget
*/
otptoken.qr_widget = function(spec) {
var that = IPA.widget(spec);
/**
* Text to be displayed as QR Code
* @property {string}
* @readonly
*/
that.text = spec.text;
/**
* Show link with the text instead of QR code
* @property {boolean}
*/
that.show_link = !!spec.show_link;
/** @inheritDoc */
that.create = function(container) {
that.widget_create(container);
container.addClass('qrcode-widget');
that.div_link_control = $('<a/>', {
name: that.name,
href: ''
}).appendTo(that.container);
that.qr_control = $('<div/>', {
name: that.name
}).appendTo(that.div_link_control);
that.uri_control = $('<div/>', {
name: 'uri-control',
'class': 'otp-uri',
style: 'display: none;'
}).appendTo(container);
that.link_container = $('<div/>', {
style: 'padding: 5px 0;'
}).appendTo(container);
that.show_uri_link = $('<a/>', {
name: 'show-uri',
href: '#',
text: text.get('@i18n:objects.otptoken.show_uri'),
click: function(e) {
e.preventDefault();
that.update_display_mode(!that.show_link);
}
}).appendTo(that.link_container);
that.qrcode = new QRCode(that.qr_control[0], {
text: "",
width: 450,
height: 450,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.M
});
that.update(that.text);
that.update_display_mode(that.show_link);
};
/**
* Update displayed information with supplied values.
* @param {String|Array|null} values
*/
that.update = function(values) {
var val;
if (typeof values === 'string') {
val = values;
} else if (values.length) {
val = values[0];
} else {
val = '';
}
that.text = val;
that.qrcode.makeCode(that.text);
that.uri_control.text(that.text);
that.div_link_control.prop('href', that.text);
that.emit('value-change', { source: that, value: val });
};
/**
* Switches between QR code and link
* @protected
* @param {boolean} show_link
*/
that.update_display_mode = function(show_link) {
that.show_link = !!show_link;
if (that.show_link) {
that.show_uri_link.text(text.get('@i18n:objects.otptoken.show_qr'));
that.qr_control.hide();
that.uri_control.show();
} else {
that.show_uri_link.text(text.get('@i18n:objects.otptoken.show_uri'));
that.qr_control.show();
that.uri_control.hide();
}
};
/**
* @inheritDoc
*/
that.clear = function() {
that.qrcode.clear();
that.link_control.text('');
};
return that;
};
/**
* Displays text as QR code in a dialog
* @class
* @extends IPA.message_dialog
*/
otptoken.qr_dialog = function(spec) {
var that = IPA.message_dialog(spec);
/**
* Uses IPA.dialog UI
*/
that.create_content = that.dialog_create_content;
return that;
};
/**
* OTP adder dialog post-op which enables showing of QR code after token is
* successfully added by displaying QR dialog.
* @member otptoken
*/
otptoken.adder_dialog_qrcode_post_op = function(object) {
object.added.attach(function(data) {
var uri = data.result.result.uri;
var qr_dialog = otptoken.qr_dialog({
name: 'qr_dialog',
title: '@i18n:objects.otptoken.config_title',
widgets: [
{
$type: 'qrcode',
name: 'qr',
css_class: 'col-sm-12',
text: uri
}
]
});
qr_dialog.open();
qr_dialog.show_message(text.get('@i18n:objects.otptoken.config_instructions'));
if (otptoken.app_link && otptoken.app_link_text) {
var app_text = text.get(otptoken.app_link_text);
app_text = app_text.replace('${link}', otptoken.app_link);
qr_dialog.show_message(app_text);
}
});
return object;
};
/**
* Entity specification object
* @member otptoken
*/
otptoken.spec = make_spec();
/**
* Register entity
* @member otptoken
*/
otptoken.register = function() {
var e = reg.entity;
var w = reg.widget;
e.register({type: 'otptoken', spec: otptoken.spec});
w.register('qrcode', otptoken.qr_widget);
};
phases.on('registration', otptoken.register);
return otptoken;
});

View File

@@ -0,0 +1,36 @@
{
"name": "freeipa",
"description": "Web UI for FreeIPA, an integrated security information management solution.",
"version": "1.0",
"keywords": ["FreeIPA","Identity management", "Red Hat", "Web UI"],
"maintainers": [{
"name": "Petr Vobornik"
}],
"contributors": [{
"name": "Petr Vobornik"
},{
"name": "Endi Sukma Dewata"
},{
"name": "Adam Young"
},{
"name": "Pavel Zuna"
},{
"name": "Ana Krivokapic"
}],
"licenses": [{
"type": "GPLv3",
"url": "http://www.gnu.org/licenses/gpl-3.0.html"
}],
"bugs": "https://fedorahosted.org/freeipa/",
"repositories": [{
"type": "git",
"url": "git://git.fedorahosted.org/git/freeipa.git ",
"path": "install/ui/js/freeipa"
}],
"dependencies": {
"dojo": "~1.8.1"
},
"main": "src",
"homepage": "http://freeipa.org/",
"dojoBuild": "freeipa.profile.js"
}

View File

@@ -0,0 +1,98 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./_base/Phase_controller'
], function(Phase_controller) {
/**
* Phases specification object.
* @ignore
* @property {string[]}
*/
var spec = {
phases: [
//'resource-load', // implicit phase
'customization',
'registration',
'login',
'init',
'metadata',
'post-metadata',
'profile',
'runtime',
'shutdown'
]
};
/**
* Phases module
*
* Provides access mainly serves as an registration point for
* phase tasks. It also provides access to Phase controller.
*
* @class phases
* @singleton
*/
var phases = {
/**
* Phases controller
*/
controller: new Phase_controller(spec),
/**
* Registers a phase task
*
* @param {string} phase_name
* @param {Function} handler Task handler. Should return promise if async.
* @param {number} [priority=10]
*/
on: function(phase_name, handler, priority) {
this.controller.add_task(phase_name, handler, priority);
},
/**
* Adds a phase
*
* Possible options:
* before: 'name-of-phase'
* after: 'name-of-phase'
* position: 'position for new phase'
*
* @param {string} phase_name
* @param {Object} options
*/
add: function(phase_name, options) {
this.controller.add_phase(phase_name, null, options);
},
/**
* Checks if phases with given name exists
*
* @param {string} name
* @return {boolean}
*/
exists: function(name) {
return this.controller.exists(name);
}
};
return phases;
});

View File

@@ -0,0 +1,99 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING'./for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/array',
'dojo/_base/lang',
'dojo/Deferred',
'dojo/promise/all'
],function(array, lang, Deferred, all) {
/**
* Plugin loader
* @class
* @singleton
*/
var plugin_loader = {
/**
* Register plugins
* @param {Array.<string>} plugins
*/
register_plugins: function(plugins) {
var packages = [];
array.forEach(plugins, function(name) {
packages.push({
name: name,
location: 'plugins/'+name
});
});
require({ packages: packages});
},
/**
* Load plugin
* @param {string} name
* @return {Promise}
*/
load_plugin: function(name) {
var plugin_loaded = new Deferred();
var mid = name+'/'+name;
require([mid], function(plugin) {
plugin_loaded.resolve(plugin);
});
return plugin_loaded.promise;
},
/**
* Load plugins
*
* - loads plugin list from `freeipa/plugins` module.
* @return {Promise}
*/
load_plugins: function() {
var plugins_loaded = new Deferred();
require(['freeipa/plugins'], function(plugins) {
var loading = [];
this.register_plugins(plugins);
array.forEach(plugins, function(plugin) {
loading.push(this.load_plugin(plugin));
}.bind(this));
all(loading).then(function(results) {
plugins_loaded.resolve(results);
});
}.bind(this));
return plugins_loaded.promise;
}
};
return plugin_loader;
});

View File

@@ -0,0 +1 @@
define([],function(){return[];});

View File

@@ -0,0 +1,105 @@
//
// Copyright (C) 2015 FreeIPA Contributors see COPYING for license
//
define(['dojo/_base/declare',
'dojo/on',
'../facets/Facet',
'../phases',
'../reg',
'../widget',
'../widgets/APIBrowserWidget',
'../builder'
],
function(declare, on, Facet, phases, reg, widget,
APIBrowserWidget, builder) {
var plugins = {}; // dummy namespace object
/**
* API browser plugin
*
* @class
* @singleton
*/
plugins.api_browser = {};
plugins.api_browser.facet_spec = {
name: 'apibrowser',
'class': 'apibrowser container-fluid',
widgets: [
{
$type: 'activity',
name: 'activity',
text: 'Working',
visible: false
},
{
$type: 'apibrowser',
name: 'apibrowser'
}
]
};
/**
* API browser facet
* @class
*/
plugins.api_browser.APIBrowserFacet = declare([Facet], {
init: function(spec) {
this.inherited(arguments);
var browser = this.get_widget('apibrowser');
on(this, 'show', function(args) {
var state = this.get_state();
var t = state.type;
var n = state.name;
if (t && n) {
browser.show_item(t, n);
return;
} else if (t) {
if (t == 'command') {
browser.show_default_command();
return;
} else {
browser.show_default_object();
return;
}
}
browser.show_default();
return;
}.bind(this));
// Reflect item change in facet state and therefore URL hash
browser.watch('current', function(name, old, value) {
var state = {};
if (value.type && value.name) {
state = { type: value.type, name: value.name };
}
this.set_state(state);
}.bind(this));
}
});
phases.on('registration', function() {
var fa = reg.facet;
var w = reg.widget;
w.register('apibrowser', APIBrowserWidget);
fa.register({
type: 'apibrowser',
factory: plugins.api_browser.APIBrowserFacet,
spec: plugins.api_browser.facet_spec
});
});
return plugins.api_browser;
});

View File

@@ -0,0 +1,91 @@
//
// Copyright (C) 2016 FreeIPA Contributors see COPYING for license
//
define([
'../ipa',
'../jquery',
'../phases',
'../reg',
'../certificate'
],
function(IPA, $, phases, reg, cert) {
/**
* ca module
* @class plugins.ca
* @singleton
*/
var ca = IPA.ca = {};
var make_ca_spec = function() {
var spec = {
name: 'ca',
facets: [
{
$type: 'search',
disable_facet_tabs: false,
tabs_in_sidebar: true,
tab_label: '@mo:ca.label',
facet_groups: [cert.facet_group],
facet_group: 'certificates',
columns: [
'cn',
'ipacasubjectdn',
'description'
]
},
{
$type: 'details',
disable_facet_tabs: true,
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
},
'ipacaid',
'ipacaissuerdn',
'ipacasubjectdn'
]
}
],
adder_dialog: {
fields: [
{
$type: 'text',
name: 'cn',
required: true
},
'ipacasubjectdn',
{
$type: 'textarea',
name: 'description'
}
]
}
};
return spec;
};
/**
* CA entity specification object
* @member plugins.ca
*/
ca.ca_spec = make_ca_spec();
/**
* Register entity
* @member plugins.ca
*/
ca.register = function() {
var e = reg.entity;
e.register({type: 'ca', spec: ca.ca_spec});
};
phases.on('registration', ca.register);
return ca;
});

View File

@@ -0,0 +1,425 @@
//
// Copyright (C) 2015 FreeIPA Contributors see COPYING for license
//
define([
'../ipa',
'../jquery',
'../phases',
'../reg',
'../certificate',
'../rule'
],
function(IPA, $, phases, reg, cert) {
/**
* caacl module
* @class plugins.caacl
* @singleton
*/
var caacl = IPA.caacl = {
remove_method_priority: IPA.config.default_priority - 1
};
var make_caacl_spec = function() {
var spec = {
name: 'caacl',
facets: [
{
$type: 'search',
disable_facet_tabs: false,
tabs_in_sidebar: true,
tab_label: '@mo:caacl.label',
facet_groups: [cert.facet_group],
facet_group: 'certificates',
row_enabled_attribute: 'ipaenabledflag',
columns: [
'cn',
{
name: 'ipaenabledflag',
label: '@i18n:status.label',
formatter: 'boolean_status'
},
'description'
],
actions: [
'batch_disable',
'batch_enable'
],
control_buttons: [
{
name: 'disable',
label: '@i18n:buttons.disable',
icon: 'fa-minus'
},
{
name: 'enable',
label: '@i18n:buttons.enable',
icon: 'fa-check'
}
]
},
{
$type: 'details',
$factory: IPA.sudorule_details_facet,
disable_facet_tabs: true,
command_mode: 'info',
actions: [
'enable',
'disable',
'delete'
],
header_actions: ['enable', 'disable', 'delete'],
state: {
evaluators: [
{
$factory: IPA.enable_state_evaluator,
field: 'ipaenabledflag'
}
],
summary_conditions: [
IPA.enabled_summary_cond,
IPA.disabled_summary_cond
]
}
}
],
adder_dialog: {
fields: [
'cn',
{
$type: 'checkboxes',
name: 'ipacacategory',
options: [
{
label: '@i18n:objects.caacl.all',
value: 'all'
}
],
tooltip: '@i18n:objects.caacl.no_ca_msg'
},
{
$type: 'textarea',
name: 'description'
}
]
}
};
add_caacl_details_facet_widgets(spec.facets[1]);
return spec;
};
/**
* @ignore
* @param {Object} facet spec
*/
var add_caacl_details_facet_widgets = function (spec) {
//
// General
//
spec.fields = [
{
name: 'cn',
read_only: true,
widget: 'general.cn'
},
{
$type: 'textarea',
name: 'description',
widget: 'general.description'
}
];
spec.widgets = [
{
$type: 'details_section',
name: 'general',
label: '@i18n:details.general',
widgets: [
{
name: 'cn'
},
{
$type: 'textarea',
name: 'description'
}
]
}
];
//
// Cert Profiles
//
spec.fields.push(
{
$type: 'radio',
name: 'ipacertprofilecategory',
widget: 'certprofile.rule.ipacertprofilecategory'
},
{
$type: 'rule_association_table',
name: 'ipamembercertprofile_certprofile',
widget: 'certprofile.rule.ipamembercertprofile_certprofile',
priority: IPA.caacl.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'certprofile',
label: '@i18n:objects.caacl.profile',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'rule',
radio_name: 'ipacertprofilecategory',
options: [
{ value: 'all',
label: '@i18n:objects.caacl.any_profile' },
{ value: '',
label: '@i18n:objects.caacl.specified_profiles' }
],
tables: [
{ name: 'ipamembercertprofile_certprofile' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'caacl-ipamembercertprofile_certprofile',
name: 'ipamembercertprofile_certprofile',
add_method: 'add_profile',
remove_method: 'remove_profile',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
}
]
}
);
//
// Who
//
spec.fields.push(
// users
{
$type: 'radio',
name: 'usercategory',
widget: 'who.user.usercategory'
},
{
$type: 'rule_association_table',
name: 'memberuser_user',
widget: 'who.user.memberuser_user',
priority: IPA.caacl.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberuser_group',
widget: 'who.user.memberuser_group',
priority: IPA.caacl.remove_method_priority
},
// hosts
{
$type: 'radio',
name: 'hostcategory',
widget: 'who.host.hostcategory'
},
{
$type: 'rule_association_table',
name: 'memberhost_host',
widget: 'who.host.memberhost_host',
priority: IPA.caacl.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberhost_hostgroup',
widget: 'who.host.memberhost_hostgroup',
priority: IPA.caacl.remove_method_priority
},
// services
{
$type: 'radio',
name: 'servicecategory',
widget: 'who.service.servicecategory'
},
{
$type: 'rule_association_table',
name: 'memberservice_service',
widget: 'who.service.memberservice_service',
priority: IPA.caacl.remove_method_priority
},
// ca
{
$type: 'radio',
name: 'ipacacategory',
widget: 'who.ipaca.ipacacategory'
},
{
$type: 'rule_association_table',
name: 'ipamemberca_ca',
widget: 'who.ipaca.ipamemberca_ca',
priority: IPA.caacl.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'who',
label: '@i18n:objects.caacl.who',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'user',
radio_name: 'usercategory',
options: [
{ value: 'all',
label: '@i18n:objects.caacl.anyone' },
{ value: '',
label: '@i18n:objects.caacl.specified_users' }
],
tables: [
{ name: 'memberuser_user' },
{ name: 'memberuser_group' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'caacl-memberuser_user',
name: 'memberuser_user',
add_method: 'add_user',
remove_method: 'remove_user',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
},
{
$type: 'rule_association_table',
id: 'caacl-memberuser_group',
name: 'memberuser_group',
add_method: 'add_user',
remove_method: 'remove_user',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
},
{
$factory: IPA.rule_details_widget,
name: 'host',
radio_name: 'hostcategory',
options: [
{
'value': 'all',
'label': '@i18n:objects.caacl.any_host'
},
{
'value': '',
'label': '@i18n:objects.caacl.specified_hosts'
}
],
tables: [
{ 'name': 'memberhost_host' },
{ 'name': 'memberhost_hostgroup' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'caacl-memberuser_user',
name: 'memberhost_host',
add_method: 'add_host',
remove_method: 'remove_host',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
},
{
$type: 'rule_association_table',
id: 'caacl-memberuser_group',
name: 'memberhost_hostgroup',
add_method: 'add_host',
remove_method: 'remove_host',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
},
{
$factory: IPA.rule_details_widget,
name: 'service',
radio_name: 'servicecategory',
options: [
{ 'value': 'all', 'label': '@i18n:objects.caacl.any_service' },
{ 'value': '', 'label': '@i18n:objects.caacl.specified_services' }
],
tables: [
{ 'name': 'memberservice_service' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'caacl-memberservice_service',
name: 'memberservice_service',
add_method: 'add_service',
remove_method: 'remove_service',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
},
{
$factory: IPA.rule_details_widget,
name: 'ipaca',
radio_name: 'ipacacategory',
note: '@i18n:objects.caacl.no_ca_msg',
options: [
{ 'value': 'all', 'label': '@i18n:objects.caacl.any_ca' },
{ 'value': '', 'label': '@i18n:objects.caacl.specified_cas' }
],
tables: [
{ 'name': 'ipamemberca_ca' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'caacl-ipamemberca_ca',
name: 'ipamemberca_ca',
add_method: 'add_ca',
remove_method: 'remove_ca',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
}
]
}
);
};
/**
* CAACL entity specification object
* @member plugins.caacl
*/
caacl.caacl_spec = make_caacl_spec();
/**
* Register entity
* @member plugins.caacl
*/
caacl.register = function() {
var e = reg.entity;
e.register({type: 'caacl', spec: caacl.caacl_spec});
};
phases.on('registration', caacl.register);
return caacl;
});

View File

@@ -0,0 +1,391 @@
//
// Copyright (C) 2017 FreeIPA Contributors see COPYING for license
//
define([
'dojo/_base/lang',
'dojo/_base/declare',
'dojo/Evented',
'dojo/on',
'../certificate',
'../navigation',
'../field',
'../ipa',
'../phases',
'../reg',
'../widget',
'../text',
'../util',
// plain imports
'../search',
'../entity'],
function(lang, declare, Evented, on, certificate, navigation,
mod_field, IPA, phases, reg, widget_mod, text, util) {
/**
* Certificate map module
* @class
*/
var certmap = IPA.certmap = {
search_facet_group: {
facets: {
certmaprule_search: 'certmaprule_search',
certmapconfig: 'certmapconfig_details',
certmapmatch: 'certmapmatch_details'
}
}
};
var make_certmaprule_spec = function() {
return {
name: 'certmaprule',
facets: [
{
$type: 'search',
always_request_members: true,
details_facet: 'details',
facet_groups: [certmap.search_facet_group],
facet_group: 'search',
row_enabled_attribute: 'ipaenabledflag',
columns: [
'cn',
{
name: 'ipaenabledflag',
label: '@i18n:status.label',
formatter: 'boolean_status'
},
'description'
],
actions: [
'batch_disable',
'batch_enable'
],
control_buttons: [
{
name: 'disable',
label: '@i18n:buttons.disable',
icon: 'fa-minus'
},
{
name: 'enable',
label: '@i18n:buttons.enable',
icon: 'fa-check'
}
]
},
{
$type: 'details',
disable_facet_tabs: true,
facet_groups: [certmap.search_facet_group],
facet_group: 'search',
actions: [
'enable',
'disable',
'delete'
],
header_actions: ['enable', 'disable', 'delete'],
state: {
evaluators: [
{
$factory: IPA.enable_state_evaluator,
field: 'ipaenabledflag'
}
]
},
sections: [
{
name: 'details',
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
},
{
name: 'ipacertmapmaprule',
tooltip: {
title: '@mc-opt:certmaprule_add:ipacertmapmaprule:doc'
}
},
{
name: 'ipacertmapmatchrule',
tooltip: {
title: '@mc-opt:certmaprule_add:ipacertmapmatchrule:doc'
}
},
{
$type: 'multivalued',
name: 'associateddomain',
tooltip: {
title: '@mc-opt:certmaprule_add:associateddomain:doc'
}
},
{
name: 'ipacertmappriority',
tooltip: {
title: '@mc-opt:certmaprule_add:ipacertmappriority:doc'
}
}
]
}
]
}
],
adder_dialog: {
fields: [
'cn',
{
name: 'ipacertmapmaprule',
tooltip: {
title: '@mc-opt:certmaprule_add:ipacertmapmaprule:doc'
}
},
{
name: 'ipacertmapmatchrule',
tooltip: {
title: '@mc-opt:certmaprule_add:ipacertmapmatchrule:doc'
}
},
{
$type: 'multivalued',
name: 'associateddomain',
tooltip: {
title: '@mc-opt:certmaprule_add:associateddomain:doc'
}
},
{
name: 'ipacertmappriority',
tooltip: {
title: '@mc-opt:certmaprule_add:ipacertmappriority:doc'
}
},
{
$type: 'textarea',
name: 'description'
}
]
}
};};
var make_certmapconfig_spec = function() {
return {
name: 'certmapconfig',
defines_key: false,
facets: [
{
$type: 'details',
facet_groups: [certmap.search_facet_group],
facet_group: 'search',
sections: [
{
name: 'details',
fields: [
{
$type: 'checkbox',
name: 'ipacertmappromptusername'
}
]
}
]
}
]
};};
/**
* Multivalued widget which is used for working with user's certmap.
*
* @class
* @extends IPA.custom_command_multivalued_widget
*/
certmap.certmap_multivalued_widget = function (spec) {
spec = spec || {};
spec.adder_dialog_spec = spec.adder_dialog_spec || {
name: 'custom-add-dialog',
title: '@i18n:objects.certmap.adder_title',
policies: [
{
$factory: IPA.multiple_choice_section_policy,
widget: 'type'
}
],
fields: [
{
$type: 'multivalued',
name: 'ipacertmapdata',
label: '@i18n:objects.certmap.data_label',
widget: 'type.ipacertmapdata'
},
{
$type: 'multivalued',
name: 'certificate',
label: '@i18n:objects.certmap.certificate',
widget: 'type.certificate',
child_spec: {
$type: 'textarea'
}
},
{
name: 'issuer',
label: '@i18n:objects.certmap.issuer',
widget: 'type.issuer'
},
{
name: 'subject',
label: '@i18n:objects.certmap.subject',
widget: 'type.subject'
}
],
widgets: [
{
$type: 'multiple_choice_section',
name: 'type',
choices: [
{
name: 'data',
label: '@i18n:objects.certmap.data_label',
fields: ['ipacertmapdata', 'certificate'],
required: [],
enabled: true
},
{
name: 'issuer_subj',
label: '@i18n:objects.certmap.issuer_subject',
fields: ['issuer', 'subject'],
required: ['issuer', 'subject']
}
],
widgets: [
{
$type: 'multivalued',
name: 'ipacertmapdata'
},
{
$type: 'multivalued',
name: 'certificate',
child_spec: {
$type: 'textarea'
},
tooltip: {
title: '@mc-opt:user_add_certmapdata:certificate:doc'
}
},
{
name: 'issuer',
tooltip: {
title: '@mc-opt:user_add_certmapdata:issuer:doc'
}
},
{
name: 'subject',
tooltip: {
title: '@mc-opt:user_add_certmapdata:subject:doc'
}
}
]
}
]
};
var that = IPA.custom_command_multivalued_widget(spec);
that.create_remove_dialog_title = function(row) {
return text.get('@i18n:objects.certmap.deleter_title');
};
that.create_remove_dialog_message = function(row) {
var message = text.get('@i18n:objects.certmap.deleter_content');
message = message.replace('${data}', row.widget.new_value);
return message;
};
/**
* Compose options for add command.
* @return {Object} options
*/
that.create_add_options = function() {
var options = {};
var widgets = that.adder_dialog.widgets.get_widgets();
var widget = widgets[0];
var inner_widgets = widget.widgets.get_widgets();
var normalize_certs = function(certs) {
for (var k = 0, l = certs.length; k<l; k++) {
certs[k] = certificate.get_base64(certs[k]);
}
};
for (var i = 0, l = inner_widgets.length; i<l; i++) {
var w = inner_widgets[i];
if (w.enabled) {
var field = that.adder_dialog.fields.get_field(w.name);
var value = field.save();
if (field.name === 'issuer' || field.name === 'subject') {
value = value[0];
} else if (field.name === 'certificate') {
normalize_certs(value);
}
if (!util.is_empty(value)) options[field.name] = value;
}
}
return options;
};
/**
* Compose options for remove command.
*
* @param {Object} row
* @return {Object} options
*/
that.create_remove_options = function(row) {
var options = {};
var data = row.widget.new_value;
options['ipacertmapdata'] = data;
return options;
};
return that;
};
/**
* Certificat Mapping Rules entity specification object
* @member certmap
*/
certmap.certmaprule_spec = make_certmaprule_spec();
/**
* Certificate Mapping Configuration entity specification object
* @member certmap
*/
certmap.certmapconfig_spec = make_certmapconfig_spec();
/**
* Register entity
* @member cermap
*/
certmap.register = function() {
var e = reg.entity;
var w = reg.widget;
e.register({type: 'certmaprule', spec: certmap.certmaprule_spec});
e.register({type: 'certmapconfig', spec: certmap.certmapconfig_spec});
w.register('certmap_multivalued',
certmap.certmap_multivalued_widget);
};
phases.on('registration', certmap.register);
return certmap;
});

View File

@@ -0,0 +1,387 @@
//
// Copyright (C) 2017 FreeIPA Contributors see COPYING for license
//
define([
'dojo/_base/lang',
'dojo/_base/declare',
'dojo/Evented',
'dojo/on',
'../metadata',
'../ipa',
'../phases',
'../reg',
'../rpc',
'../widget',
'../util',
// plain imports
'../search',
'../entity'],
function(lang, declare, Evented, on, metadata_provider, IPA, phases,
reg, rpc, widget_mod, util ) {
var certmapmatch = IPA.certmapmatch = {};
var make_certmap_spec = function() {
return {
name: 'certmap_match',
facets: [
{
$factory: certmapmatch.details_certmapmatch_facet,
disable_breadcrumb: true,
no_update: true,
name: 'cert',
label: "@i18n:objects.certmap_match.facet_label",
actions: [
'match', 'clear'
],
control_buttons: [
{
name: 'match',
title: '@i18n:buttons.match_title',
label: '@i18n:buttons.match',
icon: 'fa-gear'
},
{
name: 'clear',
title: '@i18n:buttons.clear_title',
label: '@i18n:buttons.clear',
icon: 'fa-refresh'
}
],
sections: [
{
name: 'cert_input',
label: '@i18n:objects.certmap_match.cert_for_match',
fields: [
{
$type: 'cert_textarea',
name: 'cert_textarea',
label: '@i18n:objects.cert.certificate',
autoload_value: false,
undo: false,
rows: 20,
cols: 70
}
]
},
{
name: 'parsed_cert',
label: '@i18n:objects.certmap_match.cert_data',
fields: [
{
name: 'issuer',
label: '@i18n:objects.cert.issued_by',
adapter: {
object_index: 0,
result_index: 1
},
read_only: true
},
{
name: 'subject',
label: '@i18n:objects.cert.issued_to',
adapter: {
object_index: 0,
result_index: 1
},
read_only: true
},
{
name: 'serial_number',
label: '@i18n:objects.cert.serial_number',
adapter: {
object_index: 0,
result_index: 1
},
read_only: true
},
{
name: 'serial_number_hex',
label: '@i18n:objects.cert.serial_number_hex',
adapter: {
object_index: 0,
result_index: 1
},
read_only: true
},
{
name: 'valid_not_before',
label: '@i18n:objects.cert.valid_from',
adapter: {
object_index: 0,
result_index: 1
},
read_only: true
},
{
name: 'valid_not_after',
label: '@i18n:objects.cert.valid_to',
adapter: {
object_index: 0,
result_index: 1
},
read_only: true
},
{
name: 'sha1_fingerprint',
label: '@i18n:objects.cert.sha1_fingerprint',
adapter: {
object_index: 0,
result_index: 1
},
read_only: true
},
{
name: 'sha256_fingerprint',
label: '@i18n:objects.cert.sha256_fingerprint',
adapter: {
object_index: 0,
result_index: 1
},
read_only: true
}
]
},
{
$factory: IPA.section,
name: 'divider',
layout_css_class: 'col-sm-12 col-sm-12',
fields: []
},
{
name: 'user_result_table',
label: '@i18n:objects.certmap_match.matched_users',
layout: {
$factory: widget_mod.fluid_layout,
widget_cls: "col-sm-12 col-sm-12",
label_cls: "hide"
},
layout_css_class: 'col-md-12 col-sm-12',
fields: [
{
$type: 'association_table',
name: 'result_table',
read_only: true,
selectable: false,
other_entity: 'user',
adapter: {
$type: 'certmatch_transform'
},
columns: [
{
name: 'uid',
label: '@i18n:objects.certmap_match.userlogin'
},
{
name: 'domain',
label: '@i18n:objects.certmap_match.domain'
}
]
}
]
}
]
}
]
};};
/**
* Artificial entity created from command which does not have its own entity
*
* @class certmapmatch.certmapmatch_entity
* @extends IPA.entity
*/
certmapmatch.certmapmatch_entity = function(spec) {
var that = IPA.entity(spec);
that.get_default_metadata = function() {
return metadata_provider.get('@mc:'+that.name);
};
return that;
};
/**
* Custom facet which is used for showing certmap match information
*
* @class certmapmatch.details_certmapmatch_facet
* @extends IPA.details_facet
*/
certmapmatch.details_certmapmatch_facet = function(spec) {
spec = spec || {};
var that = IPA.details_facet(spec);
that.refresh = function() {};
// always not dirty
that.is_dirty = function() {
return false;
};
that.get_result_table_widget = function() {
return that.widgets.get_widget("user_result_table.result_table");
};
that.update_result_table_summary = function(summary) {
var result_w = that.get_result_table_widget();
result_w.summary.text(summary);
};
that.clean_result = function() {
var result_w = that.get_result_table_widget();
result_w.empty();
that.update_result_table_summary('');
};
that.clean_cert_info = function() {
var widgets = that.widgets.get_widget('parsed_cert').widgets.get_widgets();
for (var i=0, l=widgets.length; i<l; i++) {
var widget = widgets[i];
widget.update();
}
};
that.obtain_cert = function() {
var cert_w = that.widgets.get_widget('cert_input.cert_textarea');
return cert_w.save();
};
that.on_cert_match = function(data) {
that.clean_result();
that.clean_cert_info();
var cert = that.obtain_cert();
if (util.is_empty(cert)) return;
var batch_command = rpc.batch_command({
name: 'certmap-match-batch',
show_error: false
});
var command = rpc.command({
method: 'certmap_match',
args: cert
});
batch_command.add_command(command);
command = rpc.command({
entity: 'cert',
method: 'find',
options: {
certificate: cert[0],
all: true
}
});
batch_command.add_command(command);
batch_command.on_success = function(data, text_status, xhr) {
// Error handling needs to be here because cert-find never fails,
// therefore batch_command always calls on_success method.
var certmatch_r = data.result.results[0];
if (certmatch_r.error === null) {
//no error
that.load(data);
that.update_result_table_summary(certmatch_r.summary);
IPA.notify_success(certmatch_r.summary);
} else {
that.update_result_table_summary(certmatch_r.error);
IPA.notify(certmatch_r.error, 'error');
}
};
batch_command.execute();
};
that.on_clear_facet = function() {
that.reset();
that.clean_result();
that.clean_cert_info();
};
that.init = function() {
on(that, 'cert-match', that.on_cert_match);
on(that, 'clear-facet', that.on_clear_facet);
};
return that;
};
/**
* Action which run certmap match.
*
* @class certmapmatch.match_action
* @extends IPA.object_action
*/
certmapmatch.match_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'match';
var that = IPA.object_action(spec);
that.execute_action = function(facet) {
facet.emit('cert-match');
};
return that;
};
/**
* Action which allows to clean whole facet.
*
* @class certmapmatch.clean_action
* @extends IPA.object_action
*/
certmapmatch.clear_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'clear';
var that = IPA.object_action(spec);
that.execute_action = function(facet) {
facet.emit('clear-facet');
};
return that;
};
/**
* Certificate Mapping Configuration entity specification object
* @member certmap
*/
certmapmatch.certmap_spec = make_certmap_spec();
/**
* Register entity
* @member cermap
*/
certmapmatch.register = function() {
var e = reg.entity;
var f = reg.field;
var a = reg.action;
a.register('match', certmapmatch.match_action);
a.register('clear', certmapmatch.clear_action);
f.register('cert_textarea', certmapmatch.cert_textarea_field);
e.register({
type: 'certmap_match',
spec: certmapmatch.certmap_spec,
factory: certmapmatch.certmapmatch_entity
});
};
phases.on('registration', certmapmatch.register);
return certmapmatch;
});

View File

@@ -0,0 +1,84 @@
//
// Copyright (C) 2015 FreeIPA Contributors see COPYING for license
//
define([
'../ipa',
'../jquery',
'../phases',
'../reg',
'../certificate'
],
function(IPA, $, phases, reg, cert) {
/**
* certprofile module
* @class plugins.certprofile
* @singleton
*/
var certprofile = IPA.certprofile = {
};
var make_certprofile_spec = function() {
return {
name: 'certprofile',
facets: [
{
$type: 'search',
$pre_ops: [
{ $del: [[ 'control_buttons', [{ name: 'add'}] ]] }
],
disable_facet_tabs: false,
tabs_in_sidebar: true,
tab_label: '@mo:certprofile.label',
facet_groups: [cert.facet_group],
facet_group: 'certificates',
columns: [
'cn',
'description',
'ipacertprofilestoreissued'
]
},
{
$type: 'details',
disable_facet_tabs: true,
sections: [
{
name: 'details',
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
},
{
$type: 'checkbox',
name: 'ipacertprofilestoreissued'
}
]
}
]
}
]
};};
/**
* Certificate profile entity specification object
* @member plugins.certprofile
*/
certprofile.certprofile_spec = make_certprofile_spec();
/**
* Register entity
* @member plugins.certprofile
*/
certprofile.register = function() {
var e = reg.entity;
e.register({type: 'certprofile', spec: certprofile.certprofile_spec});
};
phases.on('registration', certprofile.register);
return certprofile;
});

View File

@@ -0,0 +1,67 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/declare',
'dojo/_base/lang',
'dojo/on',
'../facets/Facet',
'../phases',
'../reg'
],
function(declare, lang, on, Facet, phases, reg) {
/**
* Load Facet plugin
*
* @class plugins.load
* @singleton
*/
var load = {};
load.facet_spec = {
name: 'load',
preferred_container: 'simple',
requires_auth: false,
'class': 'login-pf-body',
widgets: [
{
$type: 'activity',
name: 'activity',
text: 'Loading',
visible: true
}
]
};
phases.on('registration', function() {
var fa = reg.facet;
fa.register({
type: 'load',
factory: Facet,
spec: load.facet_spec
});
});
return load;
});

View File

@@ -0,0 +1,100 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/lang',
'dojo/on',
'../facets/Facet',
'../auth',
'../phases',
'../reg',
'../widget',
'../widgets/LoginScreen'
],
function(declare, lang, on, Facet, auth, phases, reg, widget, LoginScreen) {
/**
* Login Facet plugin
*
* Creates and registers a facet with login page.
*
* @class plugins.login
* @singleton
*/
var login = {};
login.facet_spec = {
name: 'login',
preferred_container: 'simple',
requires_auth: false,
widgets: [
{
$type: 'activity',
name: 'activity',
text: 'Authenticating',
visible: false
},
{
$type: 'login_screen',
name: 'login_screen'
}
]
};
login.LoginFacet = declare([Facet], {
can_leave: function() {
return auth.current.authenticated;
},
init: function() {
this.inherited(arguments);
var login_screen = this.get_widget('login_screen');
var self = this;
on(login_screen, 'logged_in', function(args) {
self.emit('logged_in', args);
});
on(this, 'show', function(args) {
login_screen.refresh();
});
on(login_screen, 'require-otp-sync', function(args) {
self.emit('require-otp-sync', args);
});
}
});
phases.on('registration', function() {
var fa = reg.facet;
var w = reg.widget;
w.register('login_screen', LoginScreen);
fa.register({
type: 'login',
factory: login.LoginFacet,
spec: login.facet_spec
});
});
return login;
});

View File

@@ -0,0 +1,61 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2014 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/lang',
'dojo/on',
'../ipa',
'../app_container',
'../reg',
'../phases',
'exports',
'./login',
'./sync_otp'], function(lang, on, IPA, app, reg, phases, login_process) {
/**
* Defines switching between Sync OTP facet and Login facet.
* @singleton
* @class plugins.login_process
*/
lang.mixin(login_process, {
bind_login_process: function() {
var sync_facet = reg.facet.get('sync-otp');
var login_facet = reg.facet.get('login');
on(sync_facet, 'sync-success, sync-cancel', function(args) {
app.app.show_facet(login_facet);
IPA.notify_success(args.message);
});
on(login_facet, 'require-otp-sync', function(args) {
sync_facet.set_user(args.user);
app.app.show_facet(sync_facet);
});
}
});
phases.on('init', function() {
login_process.bind_login_process();
}, 15);
return login_process;
});

View File

@@ -0,0 +1,103 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/lang',
'dojo/on',
'../facets/Facet',
'../auth',
'../navigation',
'../phases',
'../reg',
'../widget',
'../widgets/SyncOTPScreen'
],
function(declare, lang, on, Facet, auth, navigation, phases, reg, widget, SyncOTPScreen) {
/**
* Sync OTP Facet plugin
*
* Creates and registers a facet with sync otp page.
*
* @class plugins.sync_otp
* @singleton
*/
var sync_otp = {};
sync_otp.facet_spec = {
name: 'sync-otp',
'class': 'login-pf-body',
preferred_container: 'simple',
requires_auth: false,
widgets: [
{
$type: 'activity',
name: 'activity',
text: 'Synchronizing',
visible: false
},
{
$type: 'sync_otp_screen',
name: 'sync_screen'
}
]
};
sync_otp.SyncOTPFacet = declare([Facet], {
init: function() {
this.inherited(arguments);
var sync_screen = this.get_widget('sync_screen');
var self = this;
on(sync_screen, 'sync-success', function(args) {
self.emit('sync-success', args);
});
on(sync_screen, 'sync-cancel', function(args) {
self.emit('sync-cancel', args);
});
on(this, 'show', function(args) {
sync_screen.refresh();
});
},
set_user: function(user) {
var sync_screen = this.get_widget('sync_screen');
sync_screen.set('user', user);
}
});
phases.on('registration', function() {
var fa = reg.facet;
var w = reg.widget;
w.register('sync_otp_screen', SyncOTPScreen);
fa.register({
type: 'sync-otp',
factory: sync_otp.SyncOTPFacet,
spec: sync_otp.facet_spec
});
});
return sync_otp;
});

View File

@@ -0,0 +1,138 @@
/* Authors:
* Adam Young <ayoung@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./phases',
'./reg',
'./details',
'./search',
'./association',
'./entity'],
function(IPA, $, phases, reg) {
var exp = {};
exp.pwpolicy = IPA.pwpolicy = {};
var make_pwpolicy_spec = function() {
return {
name: 'pwpolicy',
facets: [
{
$type: 'search',
sort_enabled: false,
columns:['cn','cospriority']
},
{
$type: 'details',
sections:[
{
name : 'identity',
fields:[
{
$type: 'link',
name: 'cn',
other_entity: 'group'
},
'krbmaxpwdlife',
'krbminpwdlife',
{
name: 'krbpwdhistorylength',
measurement_unit: 'number_of_passwords'
},
'krbpwdmindiffchars',
'krbpwdminlength',
'krbpwdmaxfailure',
{
name: 'krbpwdfailurecountinterval',
measurement_unit: 'seconds'
},
{
name: 'krbpwdlockoutduration',
measurement_unit: 'seconds'
},
{
name: 'cospriority',
required: true
}
]
}]
}
],
standard_association_facets: true,
adder_dialog: {
fields: [
{
$type: 'entity_select',
name: 'cn',
other_entity: 'group',
other_field: 'cn',
required: true
},
{
name: 'cospriority',
required: true
}
],
height: 300
}
};};
exp.krbtpolicy = IPA.krbtpolicy = {};
var make_krbtpolicy_spec = function() {
return {
name: 'krbtpolicy',
facets: [
{
$type: 'details',
title: '@mo:krbtpolicy.label',
sections: [
{
name: 'identity',
fields: [
{
name: 'krbmaxrenewableage',
measurement_unit: 'seconds'
},
{
name: 'krbmaxticketlife',
measurement_unit: 'seconds'
}
]
}
],
needs_update: true
}
]
};};
exp.pwpolicy_spec = make_pwpolicy_spec();
exp.krbtpolicy_spec = make_krbtpolicy_spec();
exp.register = function() {
var e = reg.entity;
e.register({type: 'pwpolicy', spec: exp.pwpolicy_spec});
e.register({type: 'krbtpolicy', spec: exp.krbtpolicy_spec});
};
phases.on('registration', exp.register);
return exp;
});

View File

@@ -0,0 +1,27 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//
// AMD Wrapper for QRCode.js library
// It expects that the library was already loaded.
//
define(function() {
return window.QRCode;
});

View File

@@ -0,0 +1,133 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./menu',
'./phases',
'./reg',
'./details',
'./search',
'./entity',
'./dialogs/password'
],
function(IPA, $, menu, phases, reg) {
/**
* Radius module
* @class
* @singleton
*/
var radiusproxy = IPA.radiusproxy = {};
var make_spec = function() {
return {
name: 'radiusproxy',
enable_test: function() {
return true;
},
facets: [
{
$type: 'search',
columns: [
'cn',
'ipatokenradiusserver',
'ipatokenusermapattribute',
'description'
]
},
{
$type: 'details',
sections: [
{
name: 'details',
label: '@i18n:objects.radiusproxy.details',
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
},
{
$type: 'multivalued',
name: 'ipatokenradiusserver' // TODO: add validation
},
'ipatokenusermapattribute', // TODO: add validation
'ipatokenradiustimeout',
'ipatokenradiusretries'
]
}
],
actions: [
{
$type: 'password',
dialog: {
password_name: 'ipatokenradiussecret'
}
}
],
header_actions: ['password']
}
],
adder_dialog: {
fields: [
'cn',
{
$type: 'multivalued',
name: 'ipatokenradiusserver'
},
{
$type: 'password',
name: 'ipatokenradiussecret'
},
{
$type: 'password',
name: 'secret_verify',
label: '@i18n:password.verify_password',
flags: ['no_command'],
required: true,
validators: [{
$type: 'same_password',
other_field: 'ipatokenradiussecret'
}]
},
'ipatokenusermapattribute'
]
}
};};
/**
* Radius specification object
*/
radiusproxy.spec = make_spec();
/**
* Register radiusproxy entity
*/
radiusproxy.register = function() {
var e = reg.entity;
e.register({type: 'radiusproxy', spec: radiusproxy.spec});
};
phases.on('registration', radiusproxy.register);
return radiusproxy;
});

View File

@@ -0,0 +1,113 @@
/* Authors:
* Ana Krivokapic <akrivoka@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./phases',
'./reg',
'./details',
'./entity'],
function (IPA, $, phases, reg) {
var exp = IPA.realmdomains = {};
var make_spec = function() {
return {
name: 'realmdomains',
defines_key: false,
facets: [
{
$type: 'details',
$factory: IPA.realmdomains_details_facet,
title: '@mo:realmdomains.label',
sections: [
{
name: 'identity',
label: '@i18n:objects.realmdomains.identity',
fields: [
{
name: 'associateddomain',
$type: 'multivalued'
}
]
}
],
needs_update: true
}
]
};};
IPA.realmdomains_details_facet = function (spec) {
spec = spec || {};
var that = IPA.details_facet(spec);
that.update = function (on_success, on_error) {
var command = that.create_update_command();
command.on_success = function (data, text_status, xhr) {
that.update_on_success(data, text_status, xhr);
if (on_success) on_success.call(this, data, text_status, xhr);
};
command.on_error = function (xhr, text_status, error_thrown) {
that.update_on_error(xhr, text_status, error_thrown);
if (on_error) on_error.call(this, xhr, text_status, error_thrown);
};
var dialog = IPA.confirm_dialog({
title: '@i18n:objects.realmdomains.check_dns',
message: '@i18n:objects.realmdomains.check_dns_confirmation',
ok_label: '@i18n:objects.realmdomains.check_dns',
on_ok: function () {
command.execute();
}
});
var cancel_button = dialog.get_button('cancel');
dialog.buttons.remove('cancel');
dialog.create_button({
name: 'force',
label: '@i18n:objects.realmdomains.force_update',
visible: true,
click: function () {
command.set_option('force', true);
command.execute();
dialog.close();
}
});
dialog.add_button(cancel_button);
dialog.open();
};
return that;
};
exp.entity_spec = make_spec();
exp.register = function() {
var e = reg.entity;
e.register({type: 'realmdomains', spec: exp.entity_spec});
};
phases.on('registration', exp.register);
return exp;
});

View File

@@ -0,0 +1,91 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Registry-like object which serves as a registry of registries.
*
* Registry object should implement `register` and `get; method as Singleton or
* Construct registry do. It's expected that there will be different types of
* registries for various object types.
*
* Existing registries can be accessed directly by properties.
*
* Use set method for setting new registry.
* Use get/registry method for getting/registering object in a registry.
*
* Registries should be named by their object type in singular form:
*
* * entity
* * widget
* * action
* * formatter
* * facet
* * dialog
*
* @class reg
* @singleton
*/
define(['dojo/_base/declare',
'dojo/_base/array',
'dojo/_base/lang',
'./_base/Singleton_registry'
], function(declare, array, lang, Singleton_registry) {
var reg = new Singleton_registry();
reg.builder.ctor = Singleton_registry;
var exp = reg._map;
/**
* Get registry
* @param {string} object_type
* @param {string} type
* @return {_base.Construct_registry/_base.Singleton_registry}
*/
exp.get = function(object_type, type) {
var registry = reg.get(object_type);
return registry.get(type);
};
/**
* Create and register new registry
* @param {string} object_type
* @param {string} type
* @param {Function} func
* @param {Object} default_spec
*/
exp.register = function(object_type, type, func, default_spec) {
var registry = reg.get(object_type);
registry.register(type, func, default_spec);
};
/**
* Set new registry
* @param {string} object_type
* @param {_base.Construct_registry|_base.Singleton_registry} registry
*/
exp.set = function(object_type, registry) {
reg.set(object_type, registry);
};
return exp;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,292 @@
/* Authors:
* Endi Sukma Dewata <edewata@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./phases',
'./reg',
'./rpc',
'./text',
'./details',
'./search',
'./association',
'./entity'],
function(IPA, $, phases, reg, rpc, text) {
IPA.rule_details_widget = function(spec) {
spec = spec || {};
var that = IPA.composite_widget(spec);
that.radio_name = spec.radio_name;
that.options = spec.options || [];
that.tables = spec.tables || [];
that.columns = spec.columns;
that.note = spec.note;
that.init = function() {
that.enable_radio = IPA.rule_radio_widget({
name: that.radio_name,
options: that.options,
entity: that.entity,
css_class: 'rule-enable-radio',
note: that.note
});
that.widgets.add_widget(that.enable_radio);
that.enable_radio.value_changed.attach(that.on_enable_radio_changed);
};
that.on_enable_radio_changed = function() {
var value = that.enable_radio.save();
if(value.length > 0) {
var enabled = ('' === value[0]);
for (var i=0; i<that.tables.length; i++) {
var table = that.tables[i];
var table_widget = that.widgets.get_widget(table.name);
table_widget.set_enabled(enabled);
}
}
};
that.init();
return that;
};
/**
* Rule radio widget
*
* Intended to be used especially by rule widget.
*
* @class IPA.rule_radio_widget
* @extends IPA.radio_widget
*/
IPA.rule_radio_widget = function(spec) {
spec = spec || {};
var that = IPA.radio_widget(spec);
/**
* The text from note will be displayed after radio buttons.
*/
that.note = spec.note || '';
/** @inheritDoc */
that.create = function(container) {
var param_info = IPA.get_entity_param(that.entity.name, that.name);
var title = param_info ? param_info.doc : that.name;
container.append(document.createTextNode(title + ': '));
that.widget_create(container);
that.owb_create(container);
if (that.undo) {
that.create_undo(container);
}
if (that.note) {
$('<div />', {
text: text.get(that.note),
'class': 'rule-radio-note'
}).appendTo(container);
}
};
return that;
};
IPA.rule_association_table_widget = function(spec) {
spec = spec || {};
spec.footer = spec.footer === undefined ? false : spec.footer;
var that = IPA.association_table_widget(spec);
that.external = spec.external;
that.setup_column = function(column, div, record) {
var suppress_link = false;
if (that.external) {
suppress_link = record[that.external] === 'true';
}
column.setup(div, record, suppress_link);
};
that.create_columns = function() {
if (!that.columns.length) {
that.association_table_widget_create_columns();
if (that.external) {
that.create_column({
name: that.external,
label: '@i18n:objects.sudorule.external',
entity: that.other_entity,
formatter: 'boolean',
width: '200px'
});
}
}
};
that.create_add_dialog = function() {
var entity_label = that.entity.metadata.label_singular;
var pkey = that.facet.get_pkey();
var other_entity_label = that.other_entity.metadata.label;
var title = that.add_title;
title = title.replace('${entity}', entity_label);
title = title.replace('${primary_key}', pkey);
title = title.replace('${other_entity}', other_entity_label);
var exclude = that.values;
if (that.external) {
exclude = [];
for (var i=0; i<that.values.length; i++) {
exclude.push(that.values[i][that.name]);
}
}
return IPA.rule_association_adder_dialog({
title: title,
pkey: pkey,
other_entity: that.other_entity,
attribute_member: that.attribute_member,
entity: that.entity,
external: that.external,
exclude: exclude
});
};
return that;
};
IPA.rule_association_table_field = function(spec) {
spec = spec || {};
var that = IPA.association_table_field(spec);
that.external = spec.external;
that.set_values_external = function(values, external) {
for (var i=0; i<values.length; i++) {
var record = values[i];
if (typeof record !== 'object') {
record = {};
record[that.param] = values[i];
}
record[that.external] = external;
values[i] = record;
}
};
that.load = function(data) {
that.values = that.adapter.load(data);
if (that.external) {
that.set_values_external(that.values, '');
var external_values = that.adapter.load(data, that.external, []);
that.set_values_external(external_values, 'true');
$.merge(that.values, external_values);
}
that.widget.update(that.values);
that.widget.unselect_all();
};
that.get_update_info = function() {
var update_info = IPA.update_info_builder.new_update_info();
//association_table_widget performs basic add and remove operation
//immediately. Rule association field test if its enabled and if not it
//performs delete operation.
if (!that.widget.enabled) {
var values = that.widget.save();
if (values.length > 0) { //no need to delete if has no values
var command = rpc.command({
entity: that.entity.name,
method: that.widget.remove_method,
args: that.facet.get_pkeys()
});
command.set_option(that.widget.other_entity.name, values);
update_info.append_command(command, that.priority);
}
}
return update_info;
};
return that;
};
IPA.rule_association_adder_dialog = function(spec) {
spec = spec || {};
var that = IPA.association_adder_dialog(spec);
that.external = spec.external;
that.add = function() {
var rows = that.available_table.remove_selected_rows();
that.selected_table.add_rows(rows);
if (that.external) {
var pkey_name = that.other_entity.metadata.primary_key;
var value = that.external_field.val();
if (!value) return;
var record = {};
record[pkey_name] = value;
that.selected_table.add_record(record);
that.external_field.val('');
}
};
return that;
};
phases.on('registration', function() {
var w = reg.widget;
var f = reg.field;
w.register('rule_association_table', IPA.rule_association_table_widget);
f.register('rule_association_table', IPA.rule_association_table_field);
});
return {};
});

View File

@@ -0,0 +1,687 @@
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
* Adam Young <ayoung@redhat.com>
* Endi S. Dewata <edewata@redhat.com>
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./builder',
'./ipa',
'./jquery',
'./phases',
'./reg',
'./rpc',
'./spec_util',
'./text',
'./facet'],
function(builder, IPA, $, phases, reg, rpc, su, text, mod_facet) {
var exp = {};
exp.search_facet_control_buttons_pre_op = function(spec, context) {
var override_actions = function(cust_acts, def_acts) {
if (!cust_acts) return def_acts;
var new_default_actions = [];
for (var i=0, l=def_acts.length; i<l; i++) {
var d_action = def_acts[i];
var chosen_action = d_action;
for (var k=0, j=cust_acts.length; k<j; k++) {
var custom_act = cust_acts[k];
if (custom_act === d_action || (custom_act.$type && custom_act.$type === d_action)) {
chosen_action = custom_act;
break;
}
}
new_default_actions.push(chosen_action);
}
return new_default_actions;
};
var default_actions = ['refresh', 'batch_remove', 'add'];
var merged_actions = override_actions(spec.custom_actions, default_actions);
spec.actions = merged_actions.concat(spec.actions || []);
spec.control_buttons = spec.control_buttons || [];
if (!spec.no_update) {
spec.control_buttons.unshift(
{
name: 'remove',
label: '@i18n:buttons.remove',
icon: 'fa-trash-o'
},
{
name: 'add',
label: '@i18n:buttons.add',
icon: 'fa-plus'
});
}
spec.control_buttons.unshift(
{
name: 'refresh',
label: '@i18n:buttons.refresh',
icon: 'fa-refresh'
});
spec.state = spec.state || {};
spec.state.evaluators = spec.state.evaluators || [];
spec.state.evaluators.push(
IPA.selected_state_evaluator,
IPA.self_service_state_evaluator);
return spec;
};
exp.search_facet_pre_op = function(spec, context) {
su.context_entity(spec, context);
var entity = reg.entity.get(spec.entity);
spec.name = spec.name || 'search';
spec.title = spec.title || entity.metadata.label;
spec.label = spec.label || entity.metadata.label;
spec.tab_label = spec.tab_label || '@i18n:facets.search';
spec.managed_entity = spec.managed_entity ? IPA.get_entity(spec.managed_entity) : spec.entity;
spec.disable_breadcrumb =
spec.disable_breadcrumb === undefined ? true : spec.disable_breadcrumb;
spec.disable_facet_tabs =
spec.disable_facet_tabs === undefined ? true : spec.disable_facet_tabs;
exp.search_facet_control_buttons_pre_op(spec, context);
return spec;
};
/**
* Search facet
* @class IPA.search_facet
*/
IPA.search_facet = function(spec, no_init) {
spec = spec || {};
var that = IPA.table_facet(spec, true);
/**
* Additional command options which are added to refresh command on
* refresh.
*
* @property {Object}
*/
that.command_options = spec.command_options || {};
that.deleter_dialog = spec.deleter_dialog;
that.disable_search_field = !!spec.disable_search_field;
that.create_header = function(container) {
that.facet_create_header(container);
if (!that.disable_search_field) {
that.create_search_filter(that.controls_left);
}
that.create_control_buttons(that.controls_right);
that.create_action_dropdown(that.controls_right);
};
that.create_search_filter = function(container) {
that.filter_container = $('<div/>', {
'class': 'search-filter'
}).appendTo(container);
that.filter = $('<input/>', {
type: 'text',
'class': 'form-control',
name: 'filter',
placeholder: text.get('@i18n:search.placeholder')
}).appendTo(that.filter_container);
that.filter.keypress(function(e) {
/* if the key pressed is the enter key */
if (e.which == 13) {
that.find();
}
});
that.find_button = IPA.action_button({
name: 'find',
icon: 'fa-search',
click: function() {
that.find();
return false;
}
}).appendTo(that.filter_container);
};
that.managed_entity_pkey_prefix = function() {
if (that.entity !== that.managed_entity) {
return that.get_pkeys();
}
return that.get_pkey_prefix();
};
that.show = function() {
that.facet_show();
var filter = that.state.filter || '';
if (that.filter) {
that.filter.val(filter);
}
};
that.show_add_dialog = function() {
var dialog = that.managed_entity.get_dialog('add');
if (!that.adder_dialog) {
that.adder_dialog = dialog;
dialog.added.attach(function() {
that.refresh();
});
}
dialog.pkey_prefix = that.managed_entity_pkey_prefix();
dialog.open();
};
that.create_remove_dialog = function() {
var values = that.get_selected_values();
var title;
if (!values.length) {
title = text.get('@i18n:dialogs.remove_empty');
window.alert(title);
return null;
}
var dialog = builder.build('', that.deleter_dialog);
if (!dialog) {
dialog = that.managed_entity.get_dialog('remove');
}
if (!dialog) {
dialog = IPA.search_deleter_dialog();
}
dialog.entity_name = that.managed_entity.name;
dialog.entity = that.managed_entity;
dialog.facet = that;
dialog.pkey_prefix = that.managed_entity_pkey_prefix();
title = text.get('@i18n:dialogs.remove_title');
var label = that.managed_entity.metadata.label;
dialog.title = title.replace('${entity}', label);
dialog.set_values(values);
return dialog;
};
that.show_remove_dialog = function() {
var dialog = that.create_remove_dialog();
if (dialog) {
dialog.open();
} else {
window.console.log("Remove dialog was not created properly.");
}
};
that.find = function() {
var filter = that.filter.val();
var old_filter = that.state.filter;
var state = {};
state[that.managed_entity.name + '-filter'] = filter;
if (filter !== old_filter) that.set_expired_flag();
that.state.set({filter: filter});
};
that.get_search_command_name = function() {
var name = that.managed_entity.name + '_find';
if (that.pagination && !that.search_all_entries) {
name += '_pkeys';
}
return name;
};
that.get_refresh_command_args = function() {
var filter = that.state.filter || '';
var args = that.managed_entity_pkey_prefix();
args.push(filter);
return args;
};
/**
* Provide RPC options for refresh command
* - override point
*/
that.get_refresh_command_options = function() {
return that.command_options;
};
that.create_refresh_command = function() {
var args = that.get_refresh_command_args();
var command = rpc.command({
name: that.get_search_command_name(),
entity: that.managed_entity.name,
method: 'find',
args: args
});
command.set_options(that.get_refresh_command_options());
if (that.pagination) {
if (!that.search_all_entries) command.set_option('pkey_only', true);
command.set_option('sizelimit', 0);
}
return command;
};
that.refresh = function() {
var command = that.create_refresh_command();
command.on_success = function(data, text_status, xhr) {
if (!IPA.opened_dialogs.dialogs.length &&
!that.disable_search_field) {
that.filter.focus();
}
that.load(data);
that.show_content();
};
command.on_error = function(xhr, text_status, error_thrown) {
that.report_error(error_thrown);
};
command.execute();
};
that.clear = function() {
if (that.needs_clear()) {
that.table.clear();
}
};
that.needs_clear = function() {
var clear = false;
var filter = that.state.filter;
clear = that.old_filter !== '' || that.old_filter !== filter;
var pkeys = that.get_pkeys();
clear = clear || IPA.array_diff(pkeys, that.old_pkeys);
return clear;
};
that.init_search_facet = function() {
that.init_facet();
that.init_table_columns();
that.init_table(that.managed_entity);
that.policies.init();
};
if (!no_init) that.init_search_facet();
// methods that should be invoked by subclasses
that.search_facet_refresh = that.refresh;
that.search_facet_create_refresh_command = that.create_refresh_command;
that.search_facet_create_remove_dialog = that.create_remove_dialog;
that.search_facet_create_header = that.create_header;
that.search_facet_show = that.show;
return that;
};
IPA.search_deleter_dialog = function(spec) {
spec = spec || {};
var that = IPA.deleter_dialog(spec);
that.pkey_prefix = spec.pkey_prefix || [];
/**
* List of attributes from table from search facet, which
* are added to remove command as options. In case that there is not column
* with this name, then the option is skipped
*
* @property {String}
*/
that.additional_table_attrs = spec.additional_table_attrs || [];
that.create_command = function() {
var batch = rpc.batch_command({
error_message: '@i18n:search.partial_delete',
name: that.entity.name + '_batch_del'
});
for (var i=0; i<that.values.length; i++) {
var command = rpc.command({
entity: that.entity.name,
method: 'del'
});
if (that.pkey_prefix.length) command.add_args(that.pkey_prefix);
var value = that.values[i];
if (value instanceof Object) {
for (var key in value) {
if (value.hasOwnProperty(key)) {
if (key === 'pkey'){
value = value[key];
command.add_arg(value);
} else {
command.set_option(key, value[key]);
}
}
}
} else {
command.add_arg(value);
}
var add_attrs = that.additional_table_attrs;
if (add_attrs && add_attrs.length && add_attrs.length > 0) {
command = that.extend_command(command, add_attrs, value);
}
batch.add_command(command);
}
return batch;
};
that.execute = function() {
var batch = that.create_command();
batch.on_success = function(data, text_status, xhr) {
that.facet.refresh();
that.facet.on_update.notify([],that.facet);
that.facet.table.unselect_all();
var succeeded = batch.commands.length - batch.errors.errors.length;
var msg = text.get('@i18n:search.deleted').replace('${count}', succeeded);
IPA.notify_success(msg);
};
batch.on_error = function() {
that.facet.refresh();
};
batch.execute();
};
that.extend_command = function(command, add_attrs, pkey) {
var records = that.facet.fetch_records();
var pkey_name = that.entity.metadata.primary_key;
for (var i=0,l=records.length; i<l; i++) {
var record = records[i];
var curr_pkey = record[pkey_name][0];
if (curr_pkey && curr_pkey === pkey) {
for (var j=0,k=add_attrs.length; j<k; j++) {
var attr = add_attrs[j];
var val = record[attr];
if (val) command.set_option(attr, val);
}
}
}
return command;
};
that.search_deleter_dialog_create_command = that.create_command;
return that;
};
exp.nested_search_facet_preop = function(spec, context) {
su.context_entity(spec, context);
var entity = reg.entity.get(spec.entity);
spec.name = spec.name || 'search';
spec.title = spec.title || entity.metadata.label_singular;
spec.label = spec.label || entity.metadata.label;
spec.tab_label = spec.tab_label || '@i18n:facets.search';
spec.managed_entity = spec.nested_entity;
spec.disable_breadcrumb = false;
spec.disable_facet_tabs = false;
exp.search_facet_control_buttons_pre_op(spec, context);
return spec;
};
/*TODO. this has much copied code from above. Refactor the search_facet
To either be nested or not nested. */
exp.nested_search_facet = IPA.nested_search_facet = function(spec) {
spec = spec || {};
var that = IPA.search_facet(spec);
that.show = function() {
that.facet_show();
var pkey = that.get_pkey();
that.header.set_pkey(pkey);
var filter = that.state.filter || '';
if (that.filter) {
that.filter.val(filter);
}
};
that.refresh = function() {
var pkey = that.get_pkey();
if ((!pkey) && (that.entity.redirect_facet)) {
that.redirect();
return;
}
that.search_facet_refresh();
};
return that;
};
IPA.batch_remove_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'remove';
spec.label = spec.label || '@i18n:buttons.remove';
spec.enable_cond = spec.enable_cond || ['item-selected'];
spec.enabled = spec.enabled === undefined ? false : spec.enabled;
spec.hide_cond = spec.hide_cond || ['self-service'];
var that = IPA.action(spec);
that.execute_action = function(facet) {
facet.show_remove_dialog();
};
return that;
};
IPA.add_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'add';
spec.label = spec.label || '@i18n:buttons.add';
spec.hide_cond = spec.hide_cond || ['self-service'];
var that = IPA.action(spec);
that.execute_action = function(facet) {
facet.show_add_dialog();
};
return that;
};
/*
* Calls entity's disable command for each selected item in a batch.
* Usable in table facets.
*/
IPA.batch_items_action = function(spec) {
spec = spec || {};
var that = IPA.action(spec);
that.method = spec.method || 'disable';
that.success_msg = text.get(spec.success_msg);
that.options = spec.options || {};
that.execute_action = function(facet, on_success, on_error) {
var entity = facet.managed_entity;
var selected_keys = facet.get_selected_values();
var pkeys = facet.get_pkeys();
if (!pkeys[0]) pkeys = []; // correction for search facet
that.batch = rpc.batch_command({
name: entity.name + '_batch_'+ that.method,
on_success: that.get_on_success(facet, on_success)
});
for (var i=0; i<selected_keys.length; i++) {
var item_keys = pkeys.splice(0);
item_keys.push(selected_keys[i]);
var command = that.create_action_command(facet, item_keys);
that.batch.add_command(command);
}
that.batch.execute();
};
that.create_action_command = function(facet, keys) {
var command = rpc.command({
entity: facet.managed_entity.name,
method: that.method,
args: keys,
options: that.options
});
return command;
};
that.on_success = function(facet, data, text_status, xhr) {
facet.on_update.notify();
facet.refresh();
facet.table.unselect_all();
if (that.success_msg) {
var succeeded = that.batch.commands.length - that.batch.errors.errors.length;
var msg = that.success_msg.replace('${count}', succeeded);
IPA.notify_success(msg);
}
};
that.get_on_success = function(facet, on_success) {
return function(data, text_status, xhr) {
that.on_success(facet, data, text_status, xhr);
if (on_success) on_success.call(this, data, text_status, xhr);
};
};
return that;
};
IPA.batch_disable_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'disable';
spec.method = spec.method || 'disable';
spec.needs_confirm = spec.needs_confirm === undefined ? true : spec.needs_confirm;
spec.enable_cond = spec.enable_cond || ['item-selected'];
spec.enabled = spec.enabled === undefined ? false : spec.enabled;
spec.success_msg = spec.success_msg || '@i18n:search.disabled';
spec.confirm_msg = spec.confirm_msg || '@i18n:search.disable_confirm';
return IPA.batch_items_action(spec);
};
IPA.batch_enable_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'enable';
spec.method = spec.method || 'enable';
spec.needs_confirm = spec.needs_confirm === undefined ? true : spec.needs_confirm;
spec.enabled = spec.enabled === undefined ? false : spec.enabled;
spec.enable_cond = spec.enable_cond || ['item-selected'];
spec.success_msg = spec.success_msg || '@i18n:search.enabled';
spec.confirm_msg = spec.confirm_msg || '@i18n:search.enable_confirm';
return IPA.batch_items_action(spec);
};
exp.register = function() {
var a = reg.action;
var f = reg.facet;
a.register('batch_remove', IPA.batch_remove_action);
a.register('add', IPA.add_action);
a.register('batch_items', IPA.batch_items_action);
a.register('batch_disable', IPA.batch_disable_action);
a.register('batch_enable', IPA.batch_enable_action);
f.register({
type: 'search',
factory: IPA.search_facet,
pre_ops: [
exp.search_facet_pre_op
],
spec: { name: 'search' }
});
f.register({
type: 'nested_search',
factory: IPA.nested_search_facet,
pre_ops: [
exp.nested_search_facet_preop
],
spec: { name: 'nestedsearch' }
});
};
phases.on('registration', exp.register);
return exp;
});

View File

@@ -0,0 +1,337 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./phases',
'./reg',
'./association',
'./entity',
'./details',
'./rule',
'./search'
],
function(IPA, $, phases, reg) {
var exp = IPA.selinux = {
remove_method_priority: IPA.config.default_priority - 1
};
var make_spec = function() {
var spec = {
name: 'selinuxusermap',
facets: [
{
$type: 'search',
row_enabled_attribute: 'ipaenabledflag',
columns: [
'cn',
'ipaselinuxuser',
{
name: 'ipaenabledflag',
label: '@i18n:status.label',
formatter: 'boolean_status'
},
'description'
],
actions: [
'batch_disable',
'batch_enable'
],
control_buttons: [
{
name: 'disable',
label: '@i18n:buttons.disable',
icon: 'fa-minus'
},
{
name: 'enable',
label: '@i18n:buttons.enable',
icon: 'fa-check'
}
]
},
{
$type: 'details',
$factory: IPA.selinux_details_facet,
command_mode: 'info',
actions: [
'select',
'enable',
'disable',
'delete'
],
header_actions: ['enable', 'disable', 'delete'],
state: {
evaluators: [
{
$factory: IPA.enable_state_evaluator,
field: 'ipaenabledflag'
}
],
summary_conditions: [
IPA.enabled_summary_cond,
IPA.disabled_summary_cond
]
}
}
],
adder_dialog: {
fields: [
'cn',
'ipaselinuxuser'
]
}
};
add_selinux_details_facet_widgets(spec.facets[1]);
return spec;
};
/**
* @ignore
* @param {Object} facet spec
*/
var add_selinux_details_facet_widgets = function (spec) {
//
// General
//
spec.fields = [
{
name: 'cn',
read_only: true,
widget: 'general.cn'
},
{
$type: 'textarea',
name: 'description',
widget: 'general.description'
},
{
name: 'ipaselinuxuser',
widget: 'general.ipaselinuxuser'
},
{
$type: 'entity_select',
name: 'seealso',
widget: 'general.seealso'
}
];
spec.widgets = [
{
$type: 'details_section',
name: 'general',
label: '@i18n:details.general',
widgets: [
{
name: 'cn'
},
{
$type: 'textarea',
name: 'description'
},
{
name: 'ipaselinuxuser',
widget: 'general.ipaselinuxuser'
},
{
$type: 'entity_select',
name: 'seealso',
other_entity: 'hbacrule',
other_field: 'cn'
}
]
}
];
//
// Users
//
spec.fields.push(
{
$type: 'radio',
name: 'usercategory',
widget: 'user.rule.usercategory'
},
{
$type: 'rule_association_table',
name: 'memberuser_user',
widget: 'user.rule.memberuser_user',
priority: IPA.selinux.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberuser_group',
widget: 'user.rule.memberuser_group',
priority: IPA.selinux.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'user',
label: '@i18n:objects.selinuxusermap.user',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'rule',
radio_name: 'usercategory',
options: [
{ value: 'all',
label: '@i18n:objects.selinuxusermap.anyone' },
{ value: '',
label: '@i18n:objects.selinuxusermap.specified_users' }
],
tables: [
{ name: 'memberuser_user' },
{ name: 'memberuser_group' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'selinuxusermap-memberuser_user',
name: 'memberuser_user',
add_method: 'add_user',
remove_method: 'remove_user',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
},
{
$type: 'rule_association_table',
id: 'selinuxusermap-memberuser_group',
name: 'memberuser_group',
add_method: 'add_user',
remove_method: 'remove_user',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
}
]
}
);
//
// Hosts
//
spec.fields.push(
{
$type: 'radio',
name: 'hostcategory',
widget: 'host.rule.hostcategory'
},
{
$type: 'rule_association_table',
name: 'memberhost_host',
widget: 'host.rule.memberhost_host',
priority: IPA.selinux.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberhost_hostgroup',
widget: 'host.rule.memberhost_hostgroup',
priority: IPA.selinux.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'host',
label: '@i18n:objects.selinuxusermap.host',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'rule',
radio_name: 'hostcategory',
options: [
{
'value': 'all',
label: '@i18n:objects.selinuxusermap.any_host'
},
{
'value': '',
label: '@i18n:objects.selinuxusermap.specified_hosts'
}
],
tables: [
{ 'name': 'memberhost_host' },
{ 'name': 'memberhost_hostgroup' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'selinuxusermap-memberuser_user',
name: 'memberhost_host',
add_method: 'add_host',
remove_method: 'remove_host',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
},
{
$type: 'rule_association_table',
id: 'selinuxusermap-memberuser_group',
name: 'memberhost_hostgroup',
add_method: 'add_host',
remove_method: 'remove_host',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
}
]
}
);
};
IPA.selinux_details_facet = function(spec) {
var that = IPA.details_facet(spec);
that.update_on_success = function(data, text_status, xhr) {
that.refresh();
that.on_update.notify();
that.nofify_update_success();
};
that.update_on_error = function(xhr, text_status, error_thrown) {
that.refresh();
};
return that;
};
exp.entity_spec = make_spec();
exp.register = function() {
var e = reg.entity;
e.register({type: 'selinuxusermap', spec: exp.entity_spec});
};
phases.on('registration', exp.register);
return exp;
});

View File

@@ -0,0 +1,156 @@
/* Authors:
* Endi Sukma Dewata <edewata@redhat.com>
* Adam Young <ayoung@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./phases',
'./reg',
'./details',
'./search',
'./association',
'./entity'],
function(IPA, $, phases, reg) {
var exp = IPA.serverconfig = {};
var make_spec = function() {
return {
name: 'config',
defines_key: false,
facets: [
{
$type: 'details',
title: '@mo:config.label',
sections: [
{
name: 'search',
label: '@i18n:objects.config.search',
fields: [
'ipasearchrecordslimit',
'ipasearchtimelimit'
]
},
{
name: 'user',
label: '@i18n:objects.config.user',
fields: [
'ipausersearchfields',
'ipadefaultemaildomain',
{
name: 'ipadomainresolutionorder',
tooltip: '@mc-opt:config_mod:ipadomainresolutionorder:doc'
},
{
$type: 'entity_select',
name: 'ipadefaultprimarygroup',
other_entity: 'group',
other_field: 'cn'
},
'ipahomesrootdir',
'ipadefaultloginshell',
'ipamaxusernamelength',
'ipapwdexpadvnotify',
{
name: 'ipaconfigstring',
$type: 'checkboxes',
options: IPA.create_options([
'AllowNThash',
'KDC:Disable Last Success', 'KDC:Disable Lockout'
])
},
{
$type: 'checkboxes',
name: 'ipauserauthtype',
flags: ['w_if_no_aci'],
options: [
{ label: '@i18n:authtype.type_disabled', value: 'disabled' },
{ label: '@i18n:authtype.type_password', value: 'password' },
{ label: '@i18n:authtype.type_radius', value: 'radius' },
{ label: '@i18n:authtype.type_otp', value: 'otp' }
],
tooltip: {
title: '@i18n:authtype.config_tooltip',
html: true
}
},
{
$type: 'checkbox',
name: 'ipamigrationenabled'
},
{
$type: 'multivalued',
name: 'ipauserobjectclasses'
},
{
$type: 'entity_select',
name: 'ca_renewal_master_server',
other_entity: 'server',
other_field: 'cn',
flags: ['w_if_no_aci']
}
]
},
{
name: 'group',
label: '@i18n:objects.config.group',
fields: [
'ipagroupsearchfields',
{
$type: 'multivalued',
name: 'ipagroupobjectclasses'
}
]
},
{
name: 'selinux',
label: '@i18n:objects.config.selinux',
fields: [
'ipaselinuxusermaporder',
'ipaselinuxusermapdefault'
]
},
{
name: 'service',
label: '@i18n:objects.config.service',
fields: [
{
name: 'ipakrbauthzdata',
$type: 'checkboxes',
options: IPA.create_options(['MS-PAC', 'PAD', 'nfs:NONE'])
}
]
}
],
needs_update: true
}
]
};};
exp.entity_spec = make_spec();
exp.register = function() {
var e = reg.entity;
e.register({type: 'config', spec: exp.entity_spec});
};
phases.on('registration', exp.register);
return {};
});

View File

@@ -0,0 +1,757 @@
/* Authors:
* Endi Sukma Dewata <edewata@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/declare',
'./field',
'./builder',
'./ipa',
'./jquery',
'./phases',
'./reg',
'./rpc',
'./text',
'./details',
'./search',
'./association',
'./entity'],
function(declare, field_mod, builder, IPA, $, phases, reg, rpc, text) {
var exp =IPA.service = {};
var make_spec = function() {
return {
name: 'service',
policies: [
IPA.search_facet_update_policy,
IPA.details_facet_update_policy,
{
$factory: IPA.cert.cert_update_policy,
source_facet: 'details',
dest_entity: 'cert',
dest_facet: 'details'
},
{
$factory: IPA.cert.cert_update_policy,
source_facet: 'details',
dest_entity: 'cert',
dest_facet: 'search'
}
],
facets: [
{
$type: 'search',
$factory: IPA.service.search_facet,
columns: [
{
name: 'krbcanonicalname',
adapter: {
$type: 'alternate_attr_field_adapter',
alt_attr: 'krbprincipalname'
}
}
]
},
{
$type: 'details',
$factory: IPA.service.details_facet,
sections: [
{
name: 'details',
fields: [
{
$type: 'krb_principal_multivalued',
name: 'krbprincipalname',
item_name: 'principal',
child_spec: {
$type: 'non_editable_row',
data_name: 'krb-principal'
}
},
{
name: 'service',
label: '@i18n:objects.service.service',
read_only: true,
adapter: IPA.service_name_adapter
},
{
name: 'host',
label: '@i18n:objects.service.host',
read_only: true,
adapter: IPA.service_host_adapter
},
{
name: 'ipakrbauthzdata',
$type: 'radio',
layout: 'vertical',
options: [
{
label: '@i18n:krbauthzdata.inherited',
value: ''
},
{
label: '@i18n:krbauthzdata.override',
name: 'ipakrbauthzdata_override',
$factory: IPA.option_widget_base,
input_type: 'checkbox',
value: 'NONE',
combine_values: false,
options: [
{
label: '@i18n:krbauthzdata.mspac',
value: 'MS-PAC'
},
{
label: '@i18n:krbauthzdata.pad',
value: 'PAD'
}
]
}
]
},
{
$type: 'custom_checkboxes',
label: '@i18n:authtype.auth_indicators',
name: 'krbprincipalauthind',
add_dialog_title: '@i18n:authtype.custom_auth_ind_title',
add_field_label: '@i18n:authtype.auth_indicator',
options: [
{
label: 'otp',
value: 'otp'
},
{
label: 'radius',
value: 'radius'
}
],
tooltip: {
title: '@mc-opt:service_add:krbprincipalauthind:doc'
}
},
{
name: 'ipakrbokasdelegate',
$type: 'checkbox',
acl_param: 'krbticketflags'
},
{
name: 'ipakrboktoauthasdelegate',
$type: 'checkbox',
acl_param: 'krbticketflags'
},
{
name: 'ipakrbrequirespreauth',
$type: 'checkbox',
acl_param: 'krbticketflags'
}
]
},
{
name: 'provisioning',
fields: [
{
$type: 'service_provisioning_status',
name: 'has_keytab',
label: '@i18n:objects.service.status'
}
]
},
{
name: 'certificate',
fields: [
{
$type: 'certs',
adapter: {
$type: 'object_adapter',
result_index: 1
},
label: '@i18n:objects.cert.certificates'
}
]
},
{
$factory: IPA.section,
name: 'divider',
layout_css_class: 'col-sm-12',
fields: []
},
{
name: 'read',
label: '@i18n:keytab.allowed_to_retrieve',
$factory: IPA.section,
fields: [
{
$type: 'association_table',
id: 'service_ipaallowedtoperform_read_keys_user',
name: 'ipaallowedtoperform_read_keys_user',
add_method: 'allow_retrieve_keytab',
remove_method: 'disallow_retrieve_keytab',
add_title: '@i18n:keytab.add_retrive',
remove_title: '@i18n:keytab.remove_retrieve',
columns: [
{
name: 'ipaallowedtoperform_read_keys_user',
label: '@mo:user.label_singular',
link: true
}
]
},
{
$type: 'association_table',
id: 'service_ipaallowedtoperform_read_keys_group',
name: 'ipaallowedtoperform_read_keys_group',
add_method: 'allow_retrieve_keytab',
remove_method: 'disallow_retrieve_keytab',
add_title: '@i18n:keytab.add_retrive',
remove_title: '@i18n:keytab.remove_retrieve',
columns: [
{
name: 'ipaallowedtoperform_read_keys_group',
label: '@mo:group.label_singular',
link: true
}
]
},
{
$type: 'association_table',
id: 'service_ipaallowedtoperform_read_keys_host',
name: 'ipaallowedtoperform_read_keys_host',
add_method: 'allow_retrieve_keytab',
remove_method: 'disallow_retrieve_keytab',
add_title: '@i18n:keytab.add_retrive',
remove_title: '@i18n:keytab.remove_retrieve',
columns: [
{
name: 'ipaallowedtoperform_read_keys_host',
label: '@mo:host.label_singular',
link: true
}
]
},
{
$type: 'association_table',
id: 'service_ipaallowedtoperform_read_keys_hostgroup',
name: 'ipaallowedtoperform_read_keys_hostgroup',
add_method: 'allow_retrieve_keytab',
remove_method: 'disallow_retrieve_keytab',
add_title: '@i18n:keytab.add_retrive',
remove_title: '@i18n:keytab.remove_retrieve',
columns: [
{
name: 'ipaallowedtoperform_read_keys_hostgroup',
label: '@mo:hostgroup.label_singular',
link: true
}
]
}
]
},
{
name: 'write',
label: '@i18n:keytab.allowed_to_create',
$factory: IPA.section,
fields: [
{
$type: 'association_table',
id: 'service_ipaallowedtoperform_write_keys_user',
name: 'ipaallowedtoperform_write_keys_user',
add_method: 'allow_create_keytab',
remove_method: 'disallow_create_keytab',
add_title: '@i18n:keytab.add_create',
remove_title: '@i18n:keytab.remove_create',
columns: [
{
name: 'ipaallowedtoperform_write_keys_user',
label: '@mo:user.label_singular',
link: true
}
]
},
{
$type: 'association_table',
id: 'service_ipaallowedtoperform_write_keys_group',
name: 'ipaallowedtoperform_write_keys_group',
add_method: 'allow_create_keytab',
remove_method: 'disallow_create_keytab',
add_title: '@i18n:keytab.add_create',
remove_title: '@i18n:keytab.remove_create',
columns: [
{
name: 'ipaallowedtoperform_write_keys_group',
label: '@mo:group.label_singular',
link: true
}
]
},
{
$type: 'association_table',
id: 'service_ipaallowedtoperform_write_keys_host',
name: 'ipaallowedtoperform_write_keys_host',
add_method: 'allow_create_keytab',
remove_method: 'disallow_create_keytab',
add_title: '@i18n:keytab.add_create',
remove_title: '@i18n:keytab.remove_create',
columns: [
{
name: 'ipaallowedtoperform_write_keys_host',
label: '@mo:host.label_singular',
link: true
}
]
},
{
$type: 'association_table',
id: 'service_ipaallowedtoperform_write_keys_hostgroup',
name: 'ipaallowedtoperform_write_keys_hostgroup',
add_method: 'allow_create_keytab',
remove_method: 'disallow_create_keytab',
add_title: '@i18n:keytab.add_create',
remove_title: '@i18n:keytab.remove_create',
columns: [
{
name: 'ipaallowedtoperform_write_keys_hostgroup',
label: '@mo:hostgroup.label_singular',
link: true
}
]
}
]
}
],
actions: [
'service_unprovision',
'cert_request'
],
header_actions: [
'unprovision',
'request_cert'
],
state: {
evaluators: [
{
$factory: IPA.has_keytab_evaluator,
param: 'has_keytab',
adapter: { $type: 'batch', result_index: 0 }
},
IPA.service.krbprincipalkey_acl_evaluator,
IPA.cert.certificate_evaluator
]
},
policies: [
IPA.service.certificate_policy
]
},
{
$type: 'association',
name: 'managedby_host',
add_method: 'add_host',
remove_method: 'remove_host'
}
],
standard_association_facets: true,
adder_dialog: {
$factory: IPA.service_adder_dialog,
height: 350,
sections: [
{
fields: [
{
$type: 'combobox',
name: 'service',
label: '@i18n:objects.service.service',
options: [
'cifs',
'DNS',
'ftp',
'HTTP',
'imap',
'ldap',
'libvirt',
'nfs',
'smtp',
'qpidd'
],
editable: true,
size: 10,
required: true,
z_index: 2
},
{
$type: 'entity_select',
name: 'host',
other_entity: 'host',
other_field: 'fqdn',
label: '@i18n:objects.service.host',
required: true,
z_index: 1
},
{
$type: 'checkbox',
name: 'force',
metadata: '@mc-opt:service_add:force'
}
]
}
]
}
};};
/**
* Custom search facet for services. It has alternative primary key, in case
* that the service doesn't have canonical name.
*/
IPA.service.search_facet = function(spec) {
spec = spec || {};
spec.alternative_pkey = spec.alternative_pkey || 'krbprincipalname';
var that = IPA.search_facet(spec);
that.alternative_pkey = spec.alternative_pkey;
that.get_records_map = function(data) {
var records_map = $.ordered_map();
var pkeys_map = $.ordered_map();
var result = data.result.result;
var pkey_name = that.managed_entity.metadata.primary_key ||
that.primary_key_name;
var adapter = builder.build('adapter', 'adapter', {context: that});
for (var i=0; i<result.length; i++) {
var record = result[i];
var pkey = adapter.load(record, pkey_name)[0];
if (pkey === undefined && that.alternative_pkey) {
pkey = adapter.load(record, that.alternative_pkey)[0];
}
if (that.filter_records(records_map, pkey, record)) {
var compound_pkey = pkey + i;
records_map.put(compound_pkey, record);
pkeys_map.put(compound_pkey, pkey);
}
}
return {
records_map: records_map,
pkeys_map: pkeys_map
};
};
return that;
};
IPA.service.details_facet = function(spec, no_init) {
var that = IPA.details_facet(spec, true);
that.certificate_loaded = IPA.observer();
that.certificate_updated = IPA.observer();
that.create_refresh_command = function() {
var pkey = that.get_pkey();
var batch = rpc.batch_command({
name: 'services_details_refresh'
});
var service_command = that.details_facet_create_refresh_command();
batch.add_command(service_command);
var certificates = rpc.command({
entity: 'cert',
method: 'find',
retry: false,
options: {
service: [ pkey ],
sizelimit: 0,
all: true
}
});
batch.add_command(certificates);
return batch;
};
if (!no_init) that.init_details_facet();
return that;
};
IPA.service_adder_dialog = function(spec) {
spec = spec || {};
var that = IPA.entity_adder_dialog(spec);
var init = function() {
//small hack - krbcanonicalname should not be displayed. This way
//creation of associated widget is skipped.
//In future it would be better split section definion into widget and
//fields definition and create custom field with two associated
//widgets - 'service' and 'host' with this dialog's save logic.
that.builder.build_field({
$type: 'field',
name: 'krbcanonicalname',
required: false
});
};
that.save = function(record) {
var field = that.fields.get_field('service');
var service = field.save()[0];
field = that.fields.get_field('host');
var host = field.save()[0];
record['krbcanonicalname'] = [ service+'/'+host ];
field = that.fields.get_field('force');
record['force'] = field.save();
};
init();
return that;
};
IPA.service_name_adapter = declare([field_mod.Adapter], {
load: function(data) {
var record = this.get_record(data);
var krbprincipalname = record.krbprincipalname[0];
var value = krbprincipalname.replace(/\/.*$/, '');
return [value];
}
});
IPA.service_host_adapter = declare([field_mod.Adapter], {
load: function(data) {
var record = this.get_record(data);
var krbprincipalname = record.krbprincipalname[0];
var value = krbprincipalname.replace(/^.*\//, '').replace(/@.*$/, '');
return [value];
}
});
IPA.service_provisioning_status_widget = function (spec) {
spec = spec || {};
var that = IPA.input_widget(spec);
that.create = function(container) {
that.widget_create(container);
that.status_valid = $('<div/>', {
name: 'kerberos-key-valid',
'class': 'provisioning-status',
style: 'display: none;'
}).appendTo(container);
var content = $('<label/>', {
}).appendTo(that.status_valid);
$('<i/>', {
'class': 'fa fa-check'
}).appendTo(content);
content.append(' ');
content.append(text.get('@i18n:objects.service.valid'));
that.status_missing = $('<div/>', {
name: 'kerberos-key-missing',
'class': 'provisioning-status',
style: 'display: none;'
}).appendTo(container);
content = $('<label/>', {
}).appendTo(that.status_missing);
$('<i/>', {
'class': 'fa fa-warning'
}).appendTo(content);
content.append(' ');
content.append(text.get('@i18n:objects.service.missing'));
};
that.update = function(values) {
that.status = values && values.length ? values[0] : false;
set_status(that.status ? 'valid' : 'missing');
that.on_value_changed(values);
};
that.clear = function() {
that.status_valid.css('display', 'none');
that.status_missing.css('display', 'none');
};
function set_status(status) {
that.status_valid.css('display', status == 'valid' ? 'inline' : 'none');
that.status_missing.css('display', status == 'missing' ? 'inline' : 'none');
}
return that;
};
IPA.service.unprovision_dialog = function(spec) {
spec = spec || {};
spec.title = spec.title || '@i18n:objects.service.unprovision_title';
var that = IPA.dialog(spec);
that.facet = spec.facet;
var entity_singular = that.entity.metadata.label_singular;
that.title = that.title.replace('${entity}', entity_singular);
that.create_content = function() {
that.container.append(text.get('@i18n:objects.service.unprovision_confirmation'));
};
that.create_buttons = function() {
that.create_button({
name: 'unprovision',
label: '@i18n:objects.service.unprovision',
click: function() {
that.unprovision();
}
});
that.create_button({
name: 'cancel',
label: '@i18n:buttons.cancel',
click: function() {
that.close();
}
});
};
that.unprovision = function() {
var principal_f = that.facet.fields.get_field('krbprincipalname');
var pkey = principal_f.get_value()[0];
rpc.command({
entity: that.entity.name,
method: 'disable',
args: [pkey],
on_success: function(data, text_status, xhr) {
that.facet.refresh();
that.close();
IPA.notify_success('@i18n:objects.service.unprovisioned');
},
on_error: function(xhr, text_status, error_thrown) {
that.close();
}
}).execute();
};
that.create_buttons();
return that;
};
IPA.service.unprovision_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'unprovision';
spec.label = spec.label || '@i18n:objects.service.delete_key_unprovision';
spec.enable_cond = spec.enable_cond || ['has_keytab', 'krbprincipalkey_w'];
var that = IPA.action(spec);
that.execute_action = function(facet) {
var dialog = IPA.service.unprovision_dialog({
entity: facet.entity,
facet: facet
});
dialog.open();
};
return that;
};
IPA.service.krbprincipalkey_acl_evaluator = function(spec) {
spec.name = spec.name || 'unprovision_acl_evaluator';
spec.attribute = spec.attribute || 'krbprincipalkey';
var that = IPA.acl_state_evaluator(spec);
return that;
};
IPA.service.certificate_policy = function(spec) {
spec = spec || {};
function get_pkey(result) {
var values = result.krbprincipalname;
return values ? values[0] : null;
}
spec.get_pkey = spec.get_pkey || get_pkey;
spec.get_name = spec.get_name || function(result) {
var value = get_pkey(result);
return value ? value.replace(/@.*$/, '') : null;
};
spec.get_principal = spec.get_principal || get_pkey;
spec.get_cn = spec.get_cn || function(result) {
var value = get_pkey(result);
if (value) {
value = value.replace(/@.*$/, '').replace(/^.*\//, '');
}
return value;
};
spec.get_cn_name = spec.get_cn_name || function(result) {
return "hostname";
};
var that = IPA.cert.load_policy(spec);
return that;
};
exp.entity_spec = make_spec();
phases.on('registration', function() {
var e = reg.entity;
var w = reg.widget;
var f = reg.field;
var a = reg.action;
e.register({type: 'service', spec: exp.entity_spec});
f.register('service_provisioning_status', IPA.field);
w.register('service_provisioning_status', IPA.service_provisioning_status_widget);
a.register('service_unprovision', IPA.service.unprovision_action);
});
return exp;
});

View File

@@ -0,0 +1,85 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/array',
'dojo/_base/lang'
], function(declare, array, lang, construct) {
var undefined;
/**
* Utility for working with specification objects
* @class spec_util
* @singleton
*/
var exp = {
/**
* Set default value of spec's attribute when not already
*
* @param {Object} spec
* @param {string} attribute name
* @param {*} default value
* @param {Object} object
*/
def: function(spec, attr_name, def) {
if (spec[attr_name] === undefined) {
spec[attr_name] = def;
}
},
/**
* Set spec[spec_attr_name] to obj[attr_name].
*
* Use def value if spec doesn't contain the value.
*
* Do nothing if no value is defined.
*/
set: function(obj, spec, attr_name, def, spec_attr_name) {
spec_attr_name = spec_attr_name || attr_name;
if (spec[spec_attr_name] !== undefined) {
obj[attr_name] = spec[spec_attr_name];
} else if (def !== undefined) {
obj[attr_name] = def;
}
},
/**
* Set entity name as entity to spec if context contains entity
*/
context_entity: function(spec, context) {
if (context.entity && !spec.entity) {
if (typeof context.entity === 'string') {
spec.entity = context.entity;
} else {
spec.entity = context.entity.name;
}
}
}
};
return exp;
});

View File

@@ -0,0 +1,498 @@
//
// Copyright (C) 2015 FreeIPA Contributors see COPYING for license
//
define([
'dojo/on',
'./ipa',
'./jquery',
'./menu',
'./phases',
'./reg',
'./rpc',
'./text',
'./details',
'./facet',
'./user',
'./search',
'./entity'],
function(
on, IPA, $, menu, phases, reg, rpc, text, mod_details, mod_facet, mod_user) {
/**
* Stage user module
* @class
* @singleton
*/
var stageuser = IPA.stageuser = {
search_facet_group: {
name: 'search',
label: '@i18n:objects.stageuser.user_categories',
facets: {
search_normal: 'user_search',
search: 'stageuser_search',
search_preserved: 'user_search_preserved'
}
}
};
var make_stageuser_spec = function() {
return {
name: 'stageuser',
facet_groups: ['settings'],
policies: [
IPA.search_facet_update_policy,
IPA.details_facet_update_policy,
{
$factory: IPA.facet_update_policy,
source_facet: 'search',
dest_entity: 'user',
dest_facet: 'search'
},
{
$factory: IPA.facet_update_policy,
source_facet: 'details',
dest_entity: 'user',
dest_facet: 'search'
}
],
facets: [
{
$type: 'search',
disable_facet_tabs: false,
tabs_in_sidebar: true,
tab_label: '@i18n:objects.stageuser.label',
facet_groups: [stageuser.search_facet_group],
facet_group: 'search',
columns: [
'uid',
'givenname',
'sn',
'uidnumber',
'mail',
'telephonenumber',
'title'
],
actions: [
{
$type: 'batch_activate'
}
],
control_buttons: [
{
name: 'activate',
label: '@i18n:buttons.activate',
icon: 'fa-check'
}
],
policies: [
mod_user.stageuser_sidebar_policy
]
},
{
$type: 'details',
disable_facet_tabs: true,
sections: [
{
name: 'identity',
label: '@i18n:details.identity',
fields: [
'title',
'givenname',
'sn',
'cn',
'displayname',
'initials',
'gecos',
{
name: 'userclass',
flags: ['w_if_no_aci']
}
]
},
{
name: 'account',
label: '@i18n:objects.user.account',
fields: [
'uid',
{
$factory: mod_user.password_widget,
name: 'has_password',
metadata: '@mo-param:user:userpassword'
},
{
$type: 'datetime',
name: 'krbpasswordexpiration',
label: '@i18n:objects.user.krbpasswordexpiration',
read_only: true
},
{
name: 'uidnumber',
minvalue: -1
},
{
name: 'gidnumber',
minvalue: -1
},
'krbprincipalname',
{
$type: 'datetime',
name: 'krbprincipalexpiration'
},
'loginshell',
'homedirectory',
{
$type: 'sshkeys',
name: 'ipasshpubkey',
label: '@i18n:objects.sshkeystore.keys'
},
{
$type: 'certmap_multivalued',
name: 'ipacertmapdata',
item_name: 'certmapdata',
child_spec: {
$type: 'non_editable_row',
data_name: 'certmap'
},
tooltip: {
title: '@mc:stageuser_add_certmapdata.doc'
}
},
{
$type: 'checkboxes',
name: 'ipauserauthtype',
flags: ['w_if_no_aci'],
options: [
{ label: '@i18n:authtype.type_password', value: 'password' },
{ label: '@i18n:authtype.type_radius', value: 'radius' },
{ label: '@i18n:authtype.type_otp', value: 'otp' }
],
tooltip: '@i18n:authtype.user_tooltip'
},
{
$type: 'entity_select',
name: 'ipatokenradiusconfiglink',
flags: ['w_if_no_aci'],
other_entity: 'radiusproxy',
other_field: 'cn'
},
{
name: 'ipatokenradiususername',
flags: ['w_if_no_aci']
}
]
},
{
name: 'contact',
label: '@i18n:objects.user.contact',
fields: [
{ $type: 'multivalued', name: 'mail' },
{ $type: 'multivalued', name: 'telephonenumber' },
{ $type: 'multivalued', name: 'pager' },
{ $type: 'multivalued', name: 'mobile' },
{ $type: 'multivalued', name: 'facsimiletelephonenumber' }
]
},
{
name: 'mailing',
label: '@i18n:objects.user.mailing',
fields: ['street', 'l', 'st', 'postalcode']
},
{
name: 'employee',
label: '@i18n:objects.user.employee',
fields: [
'ou',
{
$type: 'entity_select',
name: 'manager',
other_entity: 'user',
other_field: 'uid'
},
{ $type: 'multivalued', name: 'departmentnumber' },
'employeenumber',
'employeetype',
'preferredlanguage'
]
},
{
name: 'misc',
label: '@i18n:objects.user.misc',
fields: [
{ $type: 'multivalued', name: 'carlicense' }
]
}
],
actions: [
'activate',
'delete'
],
header_actions: ['activate', 'delete'],
state: {
evaluators: [
{
$factory: mod_facet.noop_state_evaluator,
state: ['staging']
}
],
summary_conditions: [
{
pos: ['staging'],
state: ['staging'],
description: 'Staging user'
}
]
}
}
],
adder_dialog: {
sections: [
{
fields: [
{
name: 'uid',
required: false
},
'givenname',
'sn',
'userclass'
]
},
{
fields: [
{
name: 'userpassword',
label: '@i18n:password.new_password',
$type: 'password'
},
{
name: 'userpassword2',
label: '@i18n:password.verify_password',
$type: 'password',
flags: ['no_command'],
validators: [{
$type: 'same_password',
other_field: 'userpassword'
}]
}
]
}
]
}
};};
stageuser.search_preserved_facet_spec = {
$type: 'search',
$pre_ops: [
{ $del: [[ 'control_buttons', [{ name: 'add'}, { name: 'delete'}] ]] }
],
disable_facet_tabs: false,
tabs_in_sidebar: true,
entity: 'user',
managed_entity: 'user',
name: 'search_preserved',
label: '@i18n:objects.stageuser.preserved_label',
tab_label: '@i18n:objects.stageuser.preserved_label',
facet_groups: [stageuser.search_facet_group],
facet_group: 'search',
command_options: {
'preserved': true
},
columns: [
'uid',
'givenname',
'sn',
'uidnumber',
'mail',
'telephonenumber',
'title'
],
actions: [
{
$type: 'batch_undel'
},
{
$type: 'batch_stage'
}
],
control_buttons: [
{
name: 'undel',
label: '@i18n:buttons.restore',
icon: 'fa-heart'
},
{
name: 'batch_stage',
label: '@i18n:buttons.stage',
icon: 'fa-user'
}
],
policies: [
mod_user.stageuser_sidebar_policy
]
};
mod_user.entity_spec.policies = mod_user.entity_spec.policies || {};
mod_user.entity_spec.policies.push(
{
$factory: IPA.facet_update_policy,
source_facet: 'search',
dest_entity: 'stageuser',
dest_facet: 'search'
},
{
$factory: IPA.facet_update_policy,
source_facet: 'search_preserved',
dest_entity: 'stageuser',
dest_facet: 'search'
},
{
$factory: IPA.facet_update_policy,
source_facet: 'search_preserved',
dest_entity: 'user',
dest_facet: 'search'
},
{
$factory: IPA.facet_update_policy,
source_facet: 'search',
dest_entity: 'user',
dest_facet: 'search_preserved'
}
);
stageuser.batch_activate_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'activate';
spec.method = spec.method || 'activate';
spec.needs_confirm = spec.needs_confirm === undefined ? true : spec.needs_confirm;
spec.enabled = spec.enabled === undefined ? false : spec.enabled;
spec.enable_cond = spec.enable_cond || ['item-selected'];
spec.success_msg = spec.success_msg || '@i18n:objects.stageuser.activate_success';
spec.confirm_msg = spec.confirm_msg || '@i18n:objects.stageuser.activate_confirm';
return IPA.batch_items_action(spec);
};
stageuser.activate_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'activate';
spec.method = spec.method || 'activate';
spec.needs_confirm = spec.needs_confirm !== undefined ? spec.needs_confirm : true;
spec.confirm_msg = spec.confirm_msg || '@i18n:objects.stageuser.activate_one_confirm';
spec.label = spec.label || '@i18n:buttons.activate';
var that = IPA.object_action(spec);
that.on_success = function(facet, data, text_status, xhr) {
IPA.notify_success(data.result.summary);
facet.on_update.notify();
facet.redirect();
};
return that;
};
stageuser.batch_undel_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'undel';
spec.method = spec.method || 'undel';
spec.needs_confirm = spec.needs_confirm === undefined ? true : spec.needs_confirm;
spec.enabled = spec.enabled === undefined ? false : spec.enabled;
spec.enable_cond = spec.enable_cond || ['item-selected'];
spec.success_msg = spec.success_msg || '@i18n:objects.stageuser.undel_success';
spec.confirm_msg = spec.confirm_msg || '@i18n:objects.stageuser.undel_confirm';
return IPA.batch_items_action(spec);
};
stageuser.undel_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'undel';
spec.method = spec.method || 'undel';
spec.needs_confirm = spec.needs_confirm === undefined ? true : spec.needs_confirm;
spec.confirm_msg = spec.confirm_msg || '@i18n:objects.stageuser.undel_one_confirm';
spec.label = spec.label || '@i18n:buttons.restore';
var that = IPA.object_action(spec);
that.on_success = function(facet, data, text_status, xhr) {
IPA.notify_success(data.result.summary);
facet.on_update.notify();
facet.redirect();
};
return that;
};
stageuser.batch_stage_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'batch_stage';
spec.method = spec.method || 'stage';
spec.needs_confirm = spec.needs_confirm === undefined ? true : spec.needs_confirm;
spec.enable_cond = spec.enable_cond || ['item-selected'];
spec.success_msg = spec.success_msg || '@i18n:objects.stageuser.stage_success';
spec.confirm_msg = spec.confirm_msg || '@i18n:objects.stageuser.stage_confirm';
return IPA.batch_items_action(spec);
};
stageuser.stage_action = function(spec) {
spec = spec || {};
spec.name = spec.name || 'stage';
spec.method = spec.method || 'stage';
spec.show_cond = spec.show_cond || ['preserved_user'];
spec.needs_confirm = spec.needs_confirm !== undefined ? spec.needs_confirm : true;
spec.confirm_msg = spec.confirm_msg || '@i18n:objects.stageuser.stage_one_confirm';
spec.label = spec.label || '@i18n:buttons.stage';
var that = IPA.object_action(spec);
that.on_success = function(facet, data, text_status, xhr) {
IPA.notify_success(data.result.summary);
facet.on_update.notify();
facet.redirect();
};
return that;
};
/**
* Stage user entity specification object
* @member stageuser
*/
stageuser.stageuser_spec = make_stageuser_spec();
/**
* Register entity
* @member stageuser
*/
stageuser.register = function() {
var a = reg.action;
var e = reg.entity;
var f = reg.facet;
a.register('batch_activate', stageuser.batch_activate_action);
a.register('activate', stageuser.activate_action);
a.register('batch_undel', stageuser.batch_undel_action);
a.register('undel', stageuser.undel_action);
a.register('batch_stage', stageuser.batch_stage_action);
a.register('stage', stageuser.stage_action);
e.register({type: 'stageuser', spec: stageuser.stageuser_spec});
f.register_from_spec('user_search_preserved', stageuser.search_preserved_facet_spec);
};
phases.on('registration', stageuser.register);
return stageuser;
});

View File

@@ -0,0 +1,955 @@
/* Authors:
* Endi Sukma Dewata <edewata@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./phases',
'./reg',
'./rpc',
'./text',
'./association',
'./entity',
'./details',
'./rule',
'./search'
],
function(IPA, $, phases, reg, rpc, text) {
var exp = IPA.sudo = {
//priority of commands in details facet
remove_method_priority: IPA.config.default_priority - 1
};
var make_rule_spec = function() {
var spec = {
name: 'sudorule',
facets: [
{
$type: 'search',
row_enabled_attribute: 'ipaenabledflag',
columns: [
'cn',
{
name: 'ipaenabledflag',
label: '@i18n:status.label',
formatter: 'boolean_status'
},
'description'
],
actions: [
'batch_disable',
'batch_enable'
],
control_buttons: [
{
name: 'disable',
label: '@i18n:buttons.disable',
icon: 'fa-minus'
},
{
name: 'enable',
label: '@i18n:buttons.enable',
icon: 'fa-check'
}
]
},
{
$type: 'details',
$factory: IPA.sudorule_details_facet,
command_mode: 'info',
actions: [
'select',
'enable',
'disable',
'delete'
],
header_actions: ['enable', 'disable', 'delete'],
state: {
evaluators: [
{
$factory: IPA.enable_state_evaluator,
field: 'ipaenabledflag'
}
],
summary_conditions: [
IPA.enabled_summary_cond,
IPA.disabled_summary_cond
]
}
}
],
adder_dialog: {
fields: [ 'cn' ]
}
};
add_sudorule_details_facet_widgets(spec.facets[1]);
return spec;
};
var make_cmd_spec = function() {
return {
name: 'sudocmd',
facets: [
{
$type: 'search',
columns: [
'sudocmd',
'description'
]
},
{
$type: 'details',
sections: [
{
name: 'general',
label: '@i18n:details.general',
fields: [
'sudocmd',
{
$type: 'textarea',
name: 'description'
}
]
}
]
},
{
$type: 'association',
name: 'memberof_sudocmdgroup',
associator: IPA.serial_associator,
columns:[
'cn',
'description'
],
adder_columns: [
{
name: 'cn',
primary_key: true,
width: '100px'
},
{
name: 'description',
width: '100px'
}
]
}
],
standard_association_facets: true,
adder_dialog: {
fields: [
'sudocmd',
{
$type: 'textarea',
name: 'description'
}
]
}
};};
var make_cmd_group_spec = function() {
return {
name: 'sudocmdgroup',
facets: [
{
$type: 'search',
columns: [
'cn',
'description'
]
},
{
$type: 'details',
sections: [
{
name: 'general',
label: '@i18n:details.general',
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
]
},
{
$type: 'association',
name: 'member_sudocmd',
columns: [
'sudocmd',
'description'
],
adder_columns: [
{
name: 'sudocmd',
primary_key: true,
width: '100px'
},
{
name: 'description',
width: '100px'
}
]
}
],
standard_association_facets: true,
adder_dialog: {
fields: [
'cn',
{
$type: 'textarea',
name: 'description'
}
]
}
};};
/**
* @ignore
* @param {Object} facet spec
*/
var add_sudorule_details_facet_widgets = function (spec) {
//
// General
//
spec.fields = [
{
name: 'cn',
read_only: true,
widget: 'general.cn'
},
{
name: 'sudoorder',
widget: 'general.sudoorder'
},
{
$type: 'textarea',
name: 'description',
widget: 'general.description'
}
];
spec.widgets = [
{
$type: 'details_section',
name: 'general',
label: '@i18n:details.general',
widgets: [
{
name: 'cn'
},
'sudoorder',
{
$type: 'textarea',
name: 'description'
}
]
}
];
//
// Options
//
spec.fields.push(
{
name: 'ipasudoopt',
widget: 'options.ipasudoopt'
}
);
spec.widgets.push(
{
$factory: IPA.sudo.options_section,
name: 'options',
label: '@i18n:objects.sudorule.options'
}
);
//
// Users
//
spec.fields.push(
{
$type: 'radio',
name: 'usercategory',
widget: 'user.rule.usercategory'
},
{
$type: 'rule_association_table',
name: 'memberuser_user',
widget: 'user.rule.memberuser_user',
external: 'externaluser',
priority: IPA.sudo.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberuser_group',
widget: 'user.rule.memberuser_group',
priority: IPA.sudo.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'user',
label: '@i18n:objects.sudorule.user',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'rule',
radio_name: 'usercategory',
options: [
{
value: 'all',
label: '@i18n:objects.sudorule.anyone'
},
{
value: '',
label: '@i18n:objects.sudorule.specified_users'
}
],
tables: [
{ name: 'memberuser_user' },
{ name: 'memberuser_group' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'sudorule-memberuser_user',
name: 'memberuser_user',
add_method: 'add_user',
remove_method: 'remove_user',
external: 'externaluser',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
},
{
$type: 'rule_association_table',
id: 'sudorule-memberuser_group',
name: 'memberuser_group',
add_method: 'add_user',
remove_method: 'remove_user',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
}
]
}
);
//
// Hosts
//
spec.fields.push(
{
$type: 'radio',
name: 'hostcategory',
widget: 'host.rule.hostcategory'
},
{
$type: 'rule_association_table',
name: 'memberhost_host',
widget: 'host.rule.memberhost_host',
external: 'externalhost',
priority: IPA.sudo.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberhost_hostgroup',
widget: 'host.rule.memberhost_hostgroup',
priority: IPA.sudo.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'host',
label: '@i18n:objects.sudorule.host',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'rule',
radio_name: 'hostcategory',
options: [
{
'value': 'all',
label: '@i18n:objects.sudorule.any_host'
},
{
'value': '',
label: '@i18n:objects.sudorule.specified_hosts'
}
],
tables: [
{ 'name': 'memberhost_host' },
{ 'name': 'memberhost_hostgroup' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'sudorule-memberuser_user',
name: 'memberhost_host',
add_method: 'add_host',
remove_method: 'remove_host',
external: 'externalhost',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
},
{
$type: 'rule_association_table',
id: 'sudorule-memberuser_group',
name: 'memberhost_hostgroup',
add_method: 'add_host',
remove_method: 'remove_host',
add_title: '@i18n:association.add.member',
remove_title: '@i18n:association.remove.member'
}
]
}
]
}
);
//
// Run Commands
//
spec.fields.push(
{
$type: 'radio',
name: 'cmdcategory',
widget: 'command.rule.cmdcategory'
},
{
$type: 'rule_association_table',
name: 'memberallowcmd_sudocmd',
widget: 'command.rule.memberallowcmd_sudocmd',
priority: IPA.sudo.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberallowcmd_sudocmdgroup',
widget: 'command.rule.memberallowcmd_sudocmdgroup',
priority: IPA.sudo.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberdenycmd_sudocmd',
widget: 'command.rule.memberdenycmd_sudocmd',
priority: IPA.sudo.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'memberdenycmd_sudocmdgroup',
widget: 'command.rule.memberdenycmd_sudocmdgroup',
priority: IPA.sudo.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'command',
label: '@i18n:objects.sudorule.command',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'rule',
radio_name: 'cmdcategory',
options: [
{
value: 'all',
label: '@i18n:objects.sudorule.any_command'
},
{
value: '',
label: '@i18n:objects.sudorule.specified_commands'
}
],
tables: [
{ name: 'memberallowcmd_sudocmd' },
{ name: 'memberallowcmd_sudocmdgroup' },
{ name: 'memberdenycmd_sudocmd' },
{ name: 'memberdenycmd_sudocmdgroup' }
],
widgets: [
{
$factory: IPA.header_widget,
name: 'allow_header',
text: '@i18n:objects.sudorule.allow',
description: '@i18n:objects.sudorule.allow'
},
{
$type: 'rule_association_table',
id: 'sudorule-memberallowcmd_sudocmd',
name: 'memberallowcmd_sudocmd',
add_method: 'add_allow_command',
remove_method: 'remove_allow_command',
add_title: '@i18n:association.add.memberallowcmd',
remove_title: '@i18n:association.remove.memberallowcmd'
},
{
$type: 'rule_association_table',
id: 'sudorule-memberallowcmd_sudocmdgroup',
name: 'memberallowcmd_sudocmdgroup',
add_method: 'add_allow_command',
remove_method: 'remove_allow_command',
add_title: '@i18n:association.add.memberallowcmd',
remove_title: '@i18n:association.remove.memberallowcmd'
},
{
$factory: IPA.header_widget,
name: 'deny_header',
text: '@i18n:objects.sudorule.deny',
description: '@i18n:objects.sudorule.deny'
},
{
$type: 'rule_association_table',
id: 'sudorule-memberdenycmd_sudocmd',
name: 'memberdenycmd_sudocmd',
add_method: 'add_deny_command',
remove_method: 'remove_deny_command',
add_title: '@i18n:association.add.memberdenycmd',
remove_title: '@i18n:association.remove.memberdenycmd'
},
{
$type: 'rule_association_table',
id: 'sudorule-memberdenycmd_sudocmdgroup',
name: 'memberdenycmd_sudocmdgroup',
add_method: 'add_deny_command',
remove_method: 'remove_deny_command',
add_title: '@i18n:association.add.memberdenycmd',
remove_title: '@i18n:association.remove.memberdenycmd'
}
]
}
]
}
);
//
// As whom
//
spec.fields.push(
{
$type: 'radio',
name: 'ipasudorunasusercategory',
widget: 'runas.runas_users.ipasudorunasusercategory'
},
{
$type: 'rule_association_table',
name: 'ipasudorunas_user',
widget: 'runas.runas_users.ipasudorunas_user',
external: 'ipasudorunasextuser',
priority: IPA.sudo.remove_method_priority
},
{
$type: 'rule_association_table',
name: 'ipasudorunas_group',
widget: 'runas.runas_users.ipasudorunas_group',
priority: IPA.sudo.remove_method_priority
},
{
$type: 'radio',
name: 'ipasudorunasgroupcategory',
widget: 'runas.runas_groups.ipasudorunasgroupcategory'
},
{
$type: 'rule_association_table',
name: 'ipasudorunasgroup_group',
widget: 'runas.runas_groups.ipasudorunasgroup_group',
external: 'ipasudorunasextgroup',
priority: IPA.sudo.remove_method_priority
}
);
spec.widgets.push(
{
$factory: IPA.section,
name: 'runas',
label: '@i18n:objects.sudorule.runas',
widgets: [
{
$factory: IPA.rule_details_widget,
name: 'runas_users',
radio_name: 'ipasudorunasusercategory',
options: [
{ value: 'all', label: '@i18n:objects.sudorule.anyone' },
{ value: '', label: '@i18n:objects.sudorule.specified_users' }
],
tables: [
{ name: 'ipasudorunas_user' },
{ name: 'ipasudorunas_group' }
],
widgets: [
{
$type: 'rule_association_table',
id: 'sudorule-runasruser_user',
name: 'ipasudorunas_user',
external: 'ipasudorunasextuser',
add_method: 'add_runasuser',
remove_method: 'remove_runasuser',
add_title: '@i18n:association.add.ipasudorunas',
remove_title: '@i18n:association.remove.ipasudorunas'
},
{
$type: 'rule_association_table',
id: 'sudorule-runasuser_group',
name: 'ipasudorunas_group',
add_method: 'add_runasuser',
remove_method: 'remove_runasuser',
add_title: '@i18n:association.add.ipasudorunas',
remove_title: '@i18n:association.remove.ipasudorunas'
}
]
},
{
$factory: IPA.rule_details_widget,
name: 'runas_groups',
radio_name: 'ipasudorunasgroupcategory',
options: [
{ value: 'all', label: '@i18n:objects.sudorule.any_group' },
{ value: '', label: '@i18n:objects.sudorule.specified_groups' }
],
tables: [
{ name: 'ipasudorunasgroup_group' }
],
widgets: [{
$type: 'rule_association_table',
id: 'sudorule-runasgroup_group',
name: 'ipasudorunasgroup_group',
external: 'ipasudorunasextgroup',
add_method: 'add_runasgroup',
remove_method: 'remove_runasgroup',
add_title: '@i18n:association.add.ipasudorunasgroup',
remove_title: '@i18n:association.remove.ipasudorunasgroup'
}]
}
]
}
);
};
IPA.sudorule_details_facet = function(spec) {
var that = IPA.details_facet(spec);
var init = function() {
var options = that.widgets.get_widget('options');
options.facet = that;
};
that.update_on_success = function(data, text_status, xhr) {
that.refresh();
that.on_update.notify();
that.nofify_update_success();
};
that.update_on_error = function(xhr, text_status, error_thrown) {
that.refresh();
};
init();
return that;
};
IPA.sudo.options_section = function(spec) {
spec = spec || {};
var that = IPA.section(spec);
function setup_table(){
that.table = IPA.table_widget({
name: 'ipasudoopt',
show_buttons: true
});
that.widgets.add_widget(that.table);
that.table.create_column({
name: 'ipasudoopt',
label: '@mc-opt:sudorule_add_option:ipasudoopt:label',
entity: that.entity,
primary_key: true
});
that.table.create = function(container) {
that.table.table_create(container);
that.remove_button = IPA.button_widget({
name: 'remove',
label: '@i18n:buttons.remove',
icon: 'fa-trash-o',
enabled: false,
button_class: 'btn btn-link',
click: that.remove_handler
});
that.remove_button.create(that.table.buttons);
that.add_button = IPA.button_widget({
name: 'add',
label: '@i18n:buttons.add',
icon: 'fa-plus',
button_class: 'btn btn-link',
click: that.add_handler
});
that.add_button.create(that.table.buttons);
};
that.table.select_changed = function() {
var values = that.table.get_selected_values();
if (that.remove_button) {
that.remove_button.set_enabled(values.length > 0);
}
};
that.table.update = function(values) {
that.table.empty();
for (var i=0; i<values.length; i++) {
var value = values[i];
if(!value || value === '') continue;
var record = {
ipasudoopt: values[i]
};
that.table.add_record(record);
}
that.table.unselect_all();
};
}
that.add_handler = function() {
if (that.facet.is_dirty()) {
var dialog = IPA.dirty_dialog({
facet: that.facet
});
dialog.callback = function() {
that.show_add_dialog();
};
dialog.open();
} else {
that.show_add_dialog();
}
};
that.remove_handler = function() {
if (that.facet.is_dirty()) {
var dialog = IPA.dirty_dialog({
facet: that.facet
});
dialog.callback = function() {
that.show_remove_dialog();
};
dialog.open();
} else {
that.show_remove_dialog();
}
};
that.show_add_dialog = function() {
var label = IPA.get_command_option('sudorule_add_option', 'ipasudoopt').label;
var title = text.get('@i18n:dialogs.add_title');
title = title.replace('${entity}', label);
var dialog = IPA.dialog({
name: 'option-adder-dialog',
title: title,
sections: [
{
fields: [
{
name: 'ipasudoopt',
label: label
}
]
}
]
});
dialog.create_button({
name: 'add',
label: '@i18n:buttons.add',
click: function() {
var ipasudoopt = dialog.fields.get_field('ipasudoopt');
var value = ipasudoopt.save()[0];
var pkey = that.facet.get_pkey();
var command = rpc.command({
entity: 'sudorule',
method: 'add_option',
args: [pkey],
options: {
ipasudoopt: value
},
on_success: function(data) {
that.table.load(data.result.result);
dialog.close();
IPA.notify_success('@i18n:objects.sudorule.option_added');
},
on_error: function(data) {
that.reload();
dialog.close();
}
});
command.execute();
}
});
dialog.create_button({
name: 'cancel',
label: '@i18n:buttons.cancel',
click: function() {
dialog.close();
}
});
dialog.open();
};
that.show_remove_dialog = function() {
var label = IPA.get_command_option('sudorule_add_option', 'ipasudoopt').label;
var values = that.table.get_selected_values();
if (!values.length) {
var message = text.get('@i18n:dialogs.remove_empty');
window.alert(message);
return;
}
var pkey = that.facet.get_pkey();
var title = text.get('@i18n:dialogs.remove_title');
title = title.replace('${entity}', label);
var dialog = IPA.deleter_dialog({
title: title,
values: values
});
dialog.execute = function() {
var batch = rpc.batch_command({
on_success: function(data) {
//last successful result of batch results contains valid data
var result;
var succeeded = 0;
for (var i = data.result.results.length - 1; i > -1; i--) {
var error = data.result.results[i].error;
if (!result) result = data.result.results[i].result;
if (!error) succeeded++;
}
if (result) {
that.table.load(result);
} else {
that.reload();
}
var msg = text.get('@i18n:objects.sudorule.option_removed').replace('${count}', succeeded);
IPA.notify_success(msg);
},
on_error: function(data) {
that.reload();
}
});
for (var i=0; i<values.length; i++) {
var command = rpc.command({
entity: 'sudorule',
method: 'remove_option',
args: [pkey]
});
command.set_option('ipasudoopt', values[i]);
batch.add_command(command);
}
batch.execute();
};
dialog.open();
};
that.reload = function() {
var command = rpc.command({
entity: that.facet.entity.name,
method: 'show',
args: that.facet.get_pkeys(),
on_success: function(data) {
that.table.load(data.result.result);
}
});
command.execute();
};
/*initialization*/
setup_table();
return that;
};
exp.rule_spec = make_rule_spec();
exp.cmd_spec = make_cmd_spec();
exp.cmdgroup_spec = make_cmd_group_spec();
exp.register = function() {
var e = reg.entity;
e.register({type: 'sudorule', spec: exp.rule_spec});
e.register({type: 'sudocmd', spec: exp.cmd_spec});
e.register({type: 'sudocmdgroup', spec: exp.cmdgroup_spec});
};
phases.on('registration', exp.register);
return exp;
});

View File

@@ -0,0 +1,48 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2013 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['./_base/Provider', './_base/i18n', './metadata'],
function(Provider, i18n, metadata) {
/**
* Text provider
*
* Serves for returning labels, titles, messages from:
*
* - {@link _base.i18n} provider
* - and {@link metadata} provider
*
* Other providers can extends its functionality.
*
* @class text
* @singleton
* @extends _base.Provider
*/
var text = new Provider({
providers: [
i18n,
metadata
],
null_value: '',
required_type: 'string'
});
return text;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,851 @@
//
// Copyright (C) 2015 FreeIPA Contributors see COPYING for license
//
'use strict';
define([
'dojo/_base/lang',
'dojo/_base/declare',
'dojo/on',
'dojo/Evented',
'./jquery',
'libs/d3'
],
function(lang, declare, on, Evented, $, d3) {
/**
* Topology Graph module
* @class
* @singleton
*/
var topology_graph = {
};
/**
* Topology graph visualization
*
* @class
*/
topology_graph.TopoGraph = declare([Evented], {
width: 960,
height: 500,
_adder_anim_duration: 200,
_adder_inner_radius: 15,
_adder_outer_radius: 30,
_colors: d3.scale.category10(),
_svg : null,
_path: null,
_circle: null,
_create_agreement: null,
_selected_link: null,
_mousedown_link: null,
_source_node: null,
_source_node_html: null,
_target_node: null,
_drag_line: null,
/**
* Nodes - IPA servers
* id - int
*
* @property {Array}
*/
nodes: [],
/**
* Links between nodes
* @property {Array}
*/
links: [],
/**
* List of suffixes
* @property {Array}
*/
suffixes: [],
/**
* Initializes the graph
* @param {HTMLElement} container container where to put the graph svg element
*/
initialize: function(container) {
this._create_svg(container);
this.update(this.nodes, this.links, this.suffixes);
return;
},
/**
* Update the graph
* @param {Array} nodes array of node objects
* @param {Array} links array of link objects
* @param {Array} suffixes array of suffixes
*/
update: function(nodes, links, suffixes) {
var curr_trasform = this._get_stored_transformation();
var zoomed = function() {
var translate = d3.event.translate;
var scale = d3.event.scale;
var transform = "translate(" + translate + ")scale(" + scale + ")";
this._svg.selectAll('g.shapes')
.attr("transform", transform);
this._store_current_transformation();
}.bind(this);
// adds zoom behavior to the svg
var zoom = d3.behavior.zoom()
.translate(curr_trasform.translate)
.scale(curr_trasform.scale)
.scaleExtent([0.2, 1])
.on("zoom", zoomed);
// delete all from svg
this._svg.selectAll("*").remove();
this._svg.attr('width', this.width)
.attr('height', this.height)
.call(zoom);
this.links = links;
this.nodes = nodes;
this.suffixes = suffixes;
// load saved coordinates
// node.fixed uses integer
// this is useful when you need to store the original value and set
// the node temporarily fixed
for (var i=0,l=nodes.length; i<l; i++) {
var node = nodes[i];
node.fixed = 0;
if (this._get_local_storage_attr(node.id, 'fixed')) {
node.fixed = 1;
node.x = Number(this._get_local_storage_attr(node.id, 'x'));
node.y = Number(this._get_local_storage_attr(node.id, 'y'));
}
node.ca_adder = d3.svg.arc()
.innerRadius(this._adder_inner_radius)
.outerRadius(this._adder_inner_radius)
.startAngle(2 * (Math.PI/180))
.endAngle(178 * (Math.PI/180));
node.domain_adder = d3.svg.arc()
.innerRadius(this._adder_inner_radius)
.outerRadius(this._adder_inner_radius)
.startAngle(182 * (Math.PI/180))
.endAngle(358 * (Math.PI/180));
node.drag_mode = false;
}
this._init_layout();
this._define_shapes();
// handles to link and node element groups
// the order of adding shapes is important because of order of showing
// them
this._path = this._svg.append('svg:g')
.classed('shapes', true)
.selectAll('path');
this._drag_line = this._svg.append('svg:g')
.classed('shapes', true)
.append('path')
.style('marker-end', 'url(#end-arrow)')
.attr('class', 'link dragline hidden')
.attr('d', 'M0,0L0,0')
.on('click', function() {
d3.event.preventDefault();
d3.event.stopPropagation();
this._create_agreement = false;
this.reset_mouse_vars();
this._drag_line
.classed('hidden', true)
.style('marker-end', '');
this.restart();
}.bind(this));
this._circle = this._svg.append('svg:g')
.classed('shapes', true)
.selectAll('g');
this._selected_link = null;
this._mousedown_link = null;
this._selected_node = null;
this._source_node = null;
this._target_node = null;
this.restart();
},
_create_svg: function(container) {
var self = this;
this._svg = d3.select(container[0]).
append('svg').
attr('width', this.width).
attr('height', this.height).
on('mousemove', mousemove);
function mousemove(d) {
if (!self._source_node && !self._create_agreement) return;
var translate = self._get_stored_transformation();
var x = self._source_node.x;
var y = self._source_node.y;
var mouse_x = x + d3.mouse(self._source_node_html)[0];
var mouse_y = y + d3.mouse(self._source_node_html)[1];
// update drag line
self._drag_line.attr('d', 'M' + x + ',' + y + 'L' + mouse_x + ',' + mouse_y);
self.restart();
}
},
_init_layout: function() {
var l = this._layout = d3.layout.force();
l.links(this.links);
l.nodes(this.nodes);
l.size([this.width, this.height]);
l.linkDistance(150);
l.charge(-1000);
l.on('tick', this._tick.bind(this));
var that = this;
l.on('end', function () {
var nodes = l.nodes();
for (var i = 0; i < nodes.length; i++) {
var curr_node = nodes[i];
if (!curr_node.fixed) {
curr_node.fixed = 1;
that._save_node_info(curr_node);
}
}
});
},
_get_local_storage_attr: function(id, attr) {
return window.localStorage.getItem('topo_' + id + attr);
},
_set_local_storage_attr: function(id, attr, value) {
window.localStorage.setItem('topo_' + id + attr, value);
},
_remove_local_storage_attr: function(id, attr) {
window.localStorage.removeItem('topo_' + id + attr);
},
_save_node_info: function(d) {
if (d.fixed) {
this._set_local_storage_attr(d.id, 'fixed', d.fixed + '');
this._set_local_storage_attr(d.id, 'x', d.x);
this._set_local_storage_attr(d.id, 'y', d.y);
} else {
this._remove_local_storage_attr(d.id, 'fixed');
this._remove_local_storage_attr(d.id, 'x');
this._remove_local_storage_attr(d.id, 'y');
}
},
_store_current_transformation: function(d) {
var prefix = "graph_";
var translate = d3.event.translate;
var scale = d3.event.scale;
this._set_local_storage_attr(prefix, "translate", translate);
this._set_local_storage_attr(prefix, "scale", scale);
},
_get_stored_transformation: function(d) {
var prefix = "graph_";
var current_translate = this._get_local_storage_attr(prefix, "translate");
var current_scale = this._get_local_storage_attr(prefix, "scale");
if (current_translate) {
var temp_translate = current_translate.split(",");
temp_translate[0] = parseInt(temp_translate[0], 10);
temp_translate[1] = parseInt(temp_translate[1], 10);
current_translate = temp_translate;
} else {
current_translate = [0, 0];
}
if (!current_scale) {
current_scale = 1;
}
return {
translate: current_translate,
scale: current_scale
};
},
/**
* Simulation tick which
*
* - adjusts link path and position
* - node position
* - saves node position
*/
_tick: function() {
var self = this;
// draw directed edges with proper padding from node centers
this._path.attr('d', function(d) {
var node_targets = d.source.targets[d.target.id];
var target_count = node_targets.length;
target_count = target_count ? target_count : 0;
// ensure right direction of curve
var link_i = node_targets.indexOf(d);
link_i = link_i === -1 ? 0 : link_i;
var dir = link_i % 2;
if (d.source.id < d.target.id) {
dir = dir ? 0 : 1;
}
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y;
if (dx === 0) dx = 1;
if (dy === 0) dy = 1;
var dist = Math.sqrt(dx * dx + dy * dy),
ux = dx / dist, // directional vector
uy = dy / dist,
nx = -uy, // normal vector
ny = ux, // normal vector
off = dir ? -1 : 1, // determines shift direction of curve
ns = 5, // shift on normal vector
s = target_count > 1 ? 1 : 0, // shift from center?
spad = 18, // source padding
tpad = 18, // target padding
sourceX = d.source.x + (spad * ux) + off * nx * ns * s,
sourceY = d.source.y + (spad * uy) + off * ny * ns * s,
targetX = d.target.x - (tpad * ux) + off * nx * ns * s,
targetY = d.target.y - (tpad * uy) + off * ny * ns * s,
dr = s ? dist * Math.log10(dist) : 0;
return 'M' + sourceX + ',' + sourceY +
'A' + dr + " " + dr + " 0 0 " + dir +" " +
targetX + " " + targetY;
});
this._circle.attr('transform', function(d) {
self._save_node_info(d);
return 'translate(' + d.x + ',' + d.y + ')';
});
},
_get_marker_name: function(suffix, start) {
var name = suffix ? suffix.cn[0] : 'drag';
var arrow = start ? 'start-arrow' : 'end-arrow';
return name + '-' + arrow;
},
/**
* Markers on the end of links
*/
_add_marker: function(name, color, refX) {
this._svg.append('svg:defs')
.append('svg:marker')
.attr('id', name)
.attr('viewBox', '0 -5 10 10')
.attr('refX', 6)
.attr('markerWidth', 3)
.attr('markerHeight', 3)
.attr('orient', 'auto')
.append('svg:path')
.attr('d', refX)
.attr('fill', color);
},
/**
* Suffix hint so user will know which links belong to which suffix
*/
_append_suffix_hint: function(suffix, x, y) {
var color = d3.rgb(this._colors(suffix.cn[0]));
this._svg.append('svg:text')
.attr('x', x)
.attr('y', y)
.attr('class', 'suffix')
.attr('fill', color)
.text(suffix.cn[0]);
},
/**
* Defines link arrows and colors of suffixes(links) and nodes
*/
_define_shapes: function() {
var name, color;
var defs = this._svg.selectAll('defs');
defs.remove();
var x = 10;
var y = 20;
for (var i=0,l=this.suffixes.length; i<l; i++) {
var suffix = this.suffixes[i];
color = d3.rgb(this._colors(suffix.cn[0]));
name = this._get_marker_name(suffix, false);
this._add_marker(name, color, 'M0,-5L10,0L0,5');
name = this._get_marker_name(suffix, true);
this._add_marker(name, color, 'M10,-5L0,0L10,5');
this._append_suffix_hint(suffix, x, y);
y += 30;
}
},
/**
* Returns lenght of string with set class in pixels
*/
_count_string_size: function(str, cls) {
if (!str) return 0;
cls = cls || '';
var node = this._svg.append('text')
.classed(cls, true)
.text(str);
var length = node.node().getComputedTextLength();
node.remove();
return length;
},
/**
* Restart the simulation to reflect changes in data/state
*/
restart: function() {
var self = this;
// set the graph in motion
self._layout.start();
// path (link) group
this._path = this._path.data(self._layout.links());
// update existing links
this._path
.classed('selected', function(d) {
return d === self._selected_link;
})
.style('marker-start', function(d) {
var name = self._get_marker_name(d.suffix, true);
return d.left ? 'url(#'+name+')' : '';
})
.style('marker-end', function(d) {
var name = self._get_marker_name(d.suffix, false);
return d.right ? 'url(#'+name+')' : '';
});
// add new links
this._path.enter().append('svg:path')
.attr('class', 'link')
.style('stroke', function(d) {
var suffix = d.suffix ? d.suffix.cn[0] : '';
return d3.rgb(self._colors(suffix)).toString();
})
.classed('selected', function(d) {
return d === self._selected_link;
})
.style('marker-start', function(d) {
var name = self._get_marker_name(d.suffix, true);
return d.left ? 'url(#'+name+')' : '';
})
.style('marker-end', function(d) {
var name = self._get_marker_name(d.suffix, false);
return d.right ? 'url(#'+name+')' : '';
})
.on('mousedown', function(d) {
if (d3.event.ctrlKey) return;
// select link
self._mousedown_link = d;
if (self._mousedown_link === self._selected_link) {
self._selected_link = null;
} else {
self._selected_link = self._mousedown_link;
}
self.emit('link-selected', { link: self._selected_link });
self.restart();
});
// remove old links
this._path.exit().remove();
// circle (node) group
this._circle = this._circle.data(
self._layout.nodes(),
function(d) {
return d.id;
}
);
var drag = d3.behavior.drag()
.on("dragstart", dragstarted)
.on("drag", dragged)
.on("dragend", dragended);
function dragstarted(d) {
d.drag_mode = true;
hide_semicircles.bind(this, d)();
d3.event.sourceEvent.stopPropagation();
// Store the original value of fixed and set the node fixed.
d.fixed = d.fixed << 1;
d.fixed |= 1;
}
function dragged(d) {
d.px = d3.event.x;
d.py = d3.event.y;
var translate = "translate(" + d.x + "," + d.y + ")";
d3.select(this).attr('transform', translate);
self._layout.resume();
}
function dragended(d) {
d.drag_mode = false;
// Restore old value of fixed.
d.fixed = d.fixed >> 1;
self._layout.resume();
}
function add_labels(type, color, adder_group) {
var label_radius = 3;
var decimal_plus = parseInt('f067', 16); // Converts hexadecimal
// code of plus icon to decimal.
var plus = adder_group
.append('text')
.classed('plus', true)
.classed(type + '_plus', true)
.text(String.fromCharCode(decimal_plus));
var label = adder_group.append('path')
.attr('id', type + '_label');
if (type === 'ca') {
plus.attr('dx', '18')
.attr('dy', '4');
var adder_label = adder_group.append('text')
.append('textPath')
.classed('adder_label', true)
.style('fill', color)
.attr('xlink:href', '#' + type + '_label')
.text(type);
var str_size = self._count_string_size(type, 'adder_label');
var str_translate = str_size + self._adder_outer_radius + 3;
label.attr('d', 'M 33 3 L ' + str_translate + ' 3');
adder_group.insert('rect', 'text')
.attr('x', '33')
.attr('y', '-11')
.attr('rx', label_radius)
.attr('ry', label_radius)
.attr('width', str_size)
.attr('height', '18')
.style("fill", "white");
}
else {
plus.attr('dx', '-26')
.attr('dy', '4');
adder_label = adder_group.append('text')
.append('textPath')
.classed('adder_label', true)
.style('fill', color)
.attr('xlink:href', '#' + type + '_label')
.text(type);
str_size = self._count_string_size(type, 'adder_label');
str_translate = str_size + self._adder_outer_radius + 3;
label.attr('d', 'M -' + str_translate + ' 3 L -33 3');
adder_group.insert('rect', 'text')
.attr('x', '-'+str_translate)
.attr('y', '-11')
.attr('rx', label_radius)
.attr('ry', label_radius)
.attr('width', str_size)
.attr('height', '18')
.style('fill', 'white');
}
}
function create_semicircle(d, type) {
var color = d3.rgb(self._colors(type)).toString();
var adder_group = d3.select(this).select('g');
var scale = '1.05';
adder_group.append("path")
.classed(type+'_adder', true)
.classed('adder', true)
.attr("d", d[type + '_adder'])
.attr("fill", color)
.on('mouseover', function(d) {
window.clearTimeout(d._timeout_hide);
d3.select(this).attr('transform', 'scale('+scale+')');
adder_group.select('text.' + type + '_plus')
.attr('transform', 'scale('+scale+')');
})
.on('mouseout', function(d) {
d3.select(this).attr('transform', '');
adder_group.select('text.' + type + '_plus')
.attr('transform', '');
})
.on('click', function(d) {
d3.event.preventDefault();
d3.event.stopPropagation();
self.emit('link-selected', { link: null });
hide_semicircles.bind(this, d)();
// select node
if (!self._source_node) {
self._source_node = d;
self._source_node_html = d3.select(this)
.select('circle').node();
self._create_agreement = true;
}
self._selected_link = null;
var translate = self._get_stored_transformation();
var x = self._source_node.x;
var y = self._source_node.y;
// add position of node + translation of whole graph + relative
// position of the mouse
var mouse_x = d.x + d3.mouse(this)[0];
var mouse_y = d.y + d3.mouse(this)[1];
// reposition drag line
self._drag_line
.style('marker-end', 'url(#' + type + '-end-arrow)')
.style('stroke', color)
.classed('hidden', false)
.attr('suffix', type)
.attr('d', 'M' + x + ',' + y +
'L' + mouse_x + ',' + mouse_y);
self.restart();
}.bind(this))
.on('mousedown.drag', function() {
d3.event.preventDefault();
d3.event.stopPropagation();
})
.transition()
.duration(self._adder_anim_duration)
.attr("d", d[type + '_adder']
.outerRadius(self._adder_outer_radius))
.each('end', function() {
add_labels(type, color, adder_group);
});
}
function show_semicircles(d) {
if(!d3.select(this).select('g path').empty()) return;
if (!d.drag_mode && !self._create_agreement) {
// append invisible circle which covers spaces between node
// and adders it prevents hiding adders when mouse is on the space
d3.select(this).append('g')
.append('circle')
.attr('r', self._adder_outer_radius)
.style('opacity', 0);
create_semicircle.bind(this, d, 'ca')();
create_semicircle.bind(this, d, 'domain')();
//move the identification text
d3.select(this).select('text')
.transition()
.duration(self._adder_anim_duration)
.attr('dy', '45');
}
}
function hide_semicircles(d) {
var curr_nod = d3.select(this);
curr_nod.selectAll('.plus,.adder_label,rect')
.transition()
.ease('exp')
.duration(100)
.style('font-size', '0px')
.remove();
curr_nod.select('path.domain_adder')
.transition()
.attr("d", d.domain_adder
.outerRadius(self._adder_inner_radius))
.duration(self._adder_anim_duration);
curr_nod.select('path.ca_adder')
.transition()
.attr("d", d.ca_adder
.outerRadius(self._adder_inner_radius))
.duration(self._adder_anim_duration);
curr_nod.select('g')
.transition()
.duration(self._adder_anim_duration)
.remove();
curr_nod.select('text')
.transition()
.attr('dy', '30')
.duration(self._adder_anim_duration);
}
function is_suffix_shown(suffix) {
var links = self._source_node.targets[self._target_node.id];
if (!links) return false;
for (var i=0, l=links.length; i<l; i++) {
var link = links[i];
if (link.suffix.cn[0] === suffix) {
self._selected_link = link;
self.emit('link-selected', { link: link });
return true;
}
}
return false;
}
// add new nodes
var g = this._circle.enter()
.append('svg:g')
.on("dblclick", function(d) {
// Stops propagation dblclick event to the zoom behavior.
d3.event.preventDefault();
d3.event.stopPropagation();
//xor operation switch value of fixed from 1 to 0 and vice versa
d.fixed = d.fixed ^ 1;
self._layout.resume();
})
.on('mouseover', function(d) {
window.clearTimeout(d._timeout_hide);
show_semicircles.bind(this, d)();
d3.select('circle.cover').classed('cover', true);
})
.on('mouseout', function(d) {
d._timeout_hide = window.setTimeout(hide_semicircles
.bind(this, d), 50);
})
.on('click', function(d) {
if (!self._create_agreement) return;
d3.event.preventDefault();
d3.event.stopPropagation();
if (self._source_node !== d) {
self._target_node = d;
var source = self._source_node;
var target = self._target_node;
var suffix = self._drag_line.attr('suffix');
var direction = 'left';
var link = {
source: source,
target: target,
suffix: suffix,
left: false,
right: false
};
if (!is_suffix_shown(suffix)) {
link[direction] = true;
self.emit('add-agreement', link);
}
}
self._drag_line
.classed('hidden', true)
.attr('suffix', '')
.style('marker-end', '');
self.restart();
self.reset_mouse_vars();
})
.call(drag);
g.append('svg:circle')
.attr('class', 'node')
.attr('r', 12)
.style('fill', function(d) {
return self._colors(1);
})
.style('stroke', function(d) {
return d3.rgb(self._colors(1)).darker().toString();
});
// show node IDs
g.append('svg:text')
.attr('dx', 0)
.attr('dy', 30)
.attr('class', 'id')
.attr('fill', '#002235')
.text(function(d) {
return d.id.split('.')[0];
});
// remove old nodes
self._circle.exit().remove();
// get previously set position and scale of the graph and move current
// graph to the proper position
var curr_transform = this._get_stored_transformation();
var transform = "translate(" + curr_transform.translate +
")scale(" + curr_transform.scale + ")";
this._svg.selectAll('g.shapes')
.attr("transform", transform);
},
reset_mouse_vars: function() {
this._source_node = null;
this._source_node_html = null;
this._target_node = null;
this._mousedown_link = null;
this._create_agreement = null;
},
resize: function(height, width) {
if (!(isNaN(height) || isNaN(width))) {
this.height = height < 0 ? 0 : height;
this.width = width < 0 ? 0 : width;
if (this._svg) {
this._svg
.attr('width', this.width)
.attr('height', this.height);
}
}
},
constructor: function(spec) {
lang.mixin(this, spec);
}
});
return topology_graph;
});

View File

@@ -0,0 +1,480 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'./ipa',
'./jquery',
'./menu',
'./phases',
'./reg',
'./details',
'./search',
'./association',
'./entity'],
function(IPA, $, menu, phases, reg) {
var exp = IPA.trust = {};
var make_trust_spec = function() {
return {
name: 'trust',
enable_test: function() {
return IPA.trust_enabled;
},
policies: [
IPA.search_facet_update_policy,
IPA.details_facet_update_policy,
{
$factory: IPA.adder_facet_update_policy,
source_facet: 'search',
dest_entity: 'idrange',
dest_facet: 'search'
}
],
facet_groups: [ 'settings', 'trustdomain' ],
facets: [
{
$type: 'search',
columns: [
'cn'
]
},
{
$type: 'nested_search',
$pre_ops: [
// trustdomain-add is hidden, remove add button
{ $del: [[ 'control_buttons', [{ name: 'add'}] ]] }
],
nested_entity: 'trustdomain',
facet_group: 'trustdomain',
name: 'domains',
label: '@mo:trustdomain.label',
tab_label: '@mo:trustdomain.label',
search_all_entries: true,
actions: [
{
$type: 'batch_disable'
},
{
$type: 'batch_enable'
},
{
$type: 'object',
name: 'fetch',
label: '@i18n:objects.trust.fetch_domains',
method: 'fetch_domains'
}
],
control_buttons: [
{
name: 'disable',
label: '@i18n:buttons.disable',
icon: 'fa-minus'
},
{
name: 'enable',
label: '@i18n:buttons.enable',
icon: 'fa-check'
},
{
name: 'fetch',
label: '@i18n:objects.trust.fetch_domains',
icon: 'fa-download'
}
],
columns: [
{
name: 'cn',
link: false
},
{
name: 'domain_enabled',
label: '@i18n:status.label',
formatter: 'boolean_status'
},
'ipantflatname',
'ipanttrusteddomainsid'
]
},
{
$type: 'details',
sections: [
{
name: 'details',
label: '@i18n:objects.trust.details',
fields: [
'cn',
{
name: 'ipantflatname',
label: '@i18n:objects.trust.ipantflatname',
read_only: true
},
{
name: 'ipanttrusteddomainsid',
label: '@i18n:objects.trust.ipanttrusteddomainsid',
read_only: true
},
{
name: 'trustdirection',
label: '@i18n:objects.trust.trustdirection'
},
{
name: 'trusttype',
label: '@i18n:objects.trust.trusttype'
}
]
},
{
name: 'suffixes',
label: '@i18n:objects.trust.ipantadditionalsuffixes',
fields: [
{
$type: 'multivalued',
name: 'ipantadditionalsuffixes'
}
]
},
{
name: 'blacklists',
label: '@i18n:objects.trust.blacklists',
fields: [
{
$type: 'multivalued',
name: 'ipantsidblacklistincoming'
},
{
$type: 'multivalued',
name: 'ipantsidblacklistoutgoing'
}
// trust status not supported by show command at the moment
// {
// name: 'truststatus',
// label: '@i18n:objects.trust.truststatus'
// }
]
}
]
}
],
adder_dialog: {
$factory: IPA.trust.adder_dialog,
fields: [
{
name: 'cn',
label: '@i18n:objects.trust.domain',
widget: 'realm.realm_server'
},
{
$type: 'checkbox',
name: 'bidirectional',
metadata: '@mc-opt:trust_add:bidirectional',
widget: 'realm.bidirectional'
},
{
$type: 'checkbox',
name: 'external',
metadata: '@mc-opt:trust_add:external',
widget: 'realm.external'
},
{
name: 'realm_admin',
label: '@i18n:objects.trust.account',
widget: 'method.realm_admin'
},
{
$type: 'password',
name: 'realm_passwd',
label: '@i18n:password.password',
widget: 'method.realm_passwd'
},
{
$type: 'password',
name: 'trust_secret',
label: '@i18n:password.password',
widget: 'method.trust_secret'
},
{
$type: 'password',
name: 'trust_secret_verify',
label: '@i18n:password.verify_password',
widget: 'method.trust_secret_verify',
flags: ['no_command'],
validators: [{
$type: 'same_password',
other_field: 'trust_secret'
}]
},
{
$type: 'radio',
name: 'range_type',
metadata: '@mc-opt:trust_add:range_type',
widget: 'range.range_type'
},
{
name: 'base_id',
label: '@i18n:objects.idrange.ipabaseid',
metadata: '@mc-opt:trust_add:base_id',
widget: 'range.base_id'
},
{
name: 'range_size',
label: '@i18n:objects.idrange.ipaidrangesize',
metadata: '@mc-opt:trust_add:range_size',
widget: 'range.range_size'
}
],
widgets: [
{
$type: 'details_section',
name: 'realm',
widgets: [
'realm_server',
{
$type: 'checkbox',
name: 'bidirectional',
tooltip: '@mc-opt:trust_add:bidirectional:doc'
},
{
$type: 'checkbox',
name: 'external',
tooltip: '@mc-opt:trust_add:external:doc'
}
]
},
{
$type: 'multiple_choice_section',
name: 'method',
label: '@i18n:objects.trust.establish_using',
choices: [
{
name: 'admin-account',
label: '@i18n:objects.trust.admin_account',
fields: ['realm_admin', 'realm_passwd'],
required: ['realm_admin', 'realm_passwd'],
enabled: true
},
{
name: 'preshared_password',
label: '@i18n:objects.trust.preshared_password',
fields: ['trust_secret', 'trust_secret_verify'],
required: ['trust_secret', 'trust_secret_verify']
}
],
widgets: [
{
name: 'realm_admin'
},
{
$type: 'password',
name: 'realm_passwd'
},
{
$type: 'password',
name: 'trust_secret'
},
{
$type: 'password',
name: 'trust_secret_verify'
}
]
},
{
$type: 'details_section',
name: 'range',
widgets: [
{
$type: 'radio',
name: 'range_type',
layout: 'vertical',
default_value: '',
options: [
{
value: '',
label: '@i18n:objects.idrange.type_detect'
},
{
value: 'ipa-ad-trust',
label: '@i18n:objects.idrange.type_ad'
},
{
value: 'ipa-ad-trust-posix',
label: '@i18n:objects.idrange.type_ad_posix'
}
]
},
'base_id',
'range_size'
]
}
],
policies: [
{
$factory: IPA.multiple_choice_section_policy,
widget: 'method'
}
]
}
};};
IPA.trust.adder_dialog = function(spec) {
spec = spec || {};
var that = IPA.entity_adder_dialog(spec);
that.get_success_message = function(data) {
return that.entity_adder_dialog_get_success_message(data) + '. ' + data.result.result.truststatus[0];
};
that.notify_success = function(data) {
IPA.notify_success(that.get_success_message(data), 5000);
};
return that;
};
var make_trustdomain_spec = function() {
return {
name: 'trustdomain',
containing_entity: 'trust'
};};
var make_trustconfig_spec = function() {
return {
name: 'trustconfig',
defines_key: false,
enable_test: function() {
return IPA.trust_enabled;
},
facets: [
{
$type: 'details',
$factory: IPA.trust.config_details_facet,
trust_type: 'ad',
sections: [
{
name: 'details',
label: '@i18n:objects.trustconfig.options',
fields: [
'cn',
'ipantsecurityidentifier',
'ipantflatname',
'ipantdomainguid',
{
$type: 'trust_fallbackgroup_select',
name: 'ipantfallbackprimarygroup',
other_entity: 'group',
other_field: 'cn',
empty_option: false,
filter_options: {
posix: true
}
},
{
$type: 'multivalued',
name: 'ad_trust_agent_server',
read_only: true
},
{
$type: 'multivalued',
name: 'ad_trust_controller_server',
read_only: true
}
]
}
]
}
]
};};
IPA.trust.config_details_facet = function(spec) {
spec = spec || {};
var that = IPA.details_facet(spec);
that.trust_type = spec.trust_type;
that.get_refresh_command_name = function() {
return that.entity.name+that.trust_type+'_show';
};
that.create_refresh_command = function() {
var command = that.details_facet_create_refresh_command();
command.set_option('trust_type', that.trust_type);
return command;
};
that.create_update_command = function() {
var command = that.details_facet_create_update_command();
command.set_option('trust_type', that.trust_type);
return command;
};
return that;
};
IPA.trust.fallbackgroup_select_widget = function(spec) {
var that = IPA.entity_select_widget(spec);
that.set_options = function(options) {
// always add 'Default SMB Group', it can't be obtained by group-find.
options.unshift('Default SMB Group');
that.entity_select_set_options(options);
};
return that;
};
exp.remove_menu_item = function() {
if (!IPA.trust_enabled) {
menu.remove_item('ipaserver/trusts');
}
};
exp.trust_spec = make_trust_spec();
exp.trustdomain_spec = make_trustdomain_spec();
exp.trustconfig_spec = make_trustconfig_spec();
IPA.trust.register = function() {
var e = reg.entity;
var w = reg.widget;
var f = reg.field;
e.register({type: 'trust', spec: exp.trust_spec});
e.register({type: 'trustdomain', spec: exp.trustdomain_spec});
e.register({type: 'trustconfig', spec: exp.trustconfig_spec});
w.register('trust_fallbackgroup_select', IPA.trust.fallbackgroup_select_widget);
f.register('trust_fallbackgroup_select', IPA.field);
};
phases.on('registration', IPA.trust.register);
phases.on('profile', exp.remove_menu_item, 20);
return exp;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,384 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2014 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'dojo/_base/lang',
'./text'
],
function(lang, text) {
function equals_obj_def(a, b, options) {
var same = true;
var checked = {};
var check_same = function(a, b, skip) {
var same = true;
skip = skip || {};
for (var key in a) {
if (a.hasOwnProperty(key) && !(key in skip)) {
var va = a[key];
var vb = b[key];
if (!equals(va, vb, options)) {
same = false;
skip[a] = true;
break;
}
}
}
return same;
};
same = check_same(a,b, checked);
same = same && check_same(b,a, checked);
return same;
}
function equals_obj(a, b, options) {
if (options.comparator) {
return options.comparator(a, b, options);
} else {
return equals_obj_def(a, b, options);
}
}
function equals_array(a1, b1, options) {
var a = a1,
b = b1;
if (!a || !b) return false;
if (a1.length !== b1.length) return false;
if (options.unordered) {
a = a1.slice(0);
b = b1.slice(0);
a.sort();
b.sort();
}
for (var i=0; i<a.length; i++) {
if (!equals(a[i], b[i], options)) return false;
}
return true;
}
function equals(a, b, options) {
var a_t = typeof a;
var b_t = typeof b;
options = options || {};
if (a_t !== b_t) return false;
if (a === b) return true;
if (['string', 'number', 'function', 'boolean',
'undefined'].indexOf(a_t) > -1) {
return false;
} else if (a === null || b === null) {
return false;
} else if (lang.isArray(a)) {
return equals_array(a, b, options);
} else if (a instanceof Date) {
return a.getTime() === b.getTime();
} else { // objects
return equals_obj(a, b, options);
}
}
function is_empty(value) {
var empty = false;
if (value === null || value === undefined) empty = true;
if (lang.isArray(value)) {
empty = empty || value.length === 0 ||
(value.length === 1) && (value[0] === '');
} else if (typeof value === 'object') {
var has_p = false;
for (var p in value) {
if (value.hasOwnProperty(p)) {
has_p = true;
break;
}
}
empty = !has_p;
} else if (value === '') empty = true;
return empty;
}
function dirty(value, pristine, options) {
// check for empty value: null, [''], '', []
var orig_empty = is_empty(pristine);
var new_empty= is_empty(value);
if (orig_empty && new_empty) return false;
if (orig_empty != new_empty) return true;
// strict equality - checks object's ref equality, numbers, strings
if (value === pristine) return false;
return !equals(value, pristine, options);
}
function format_single(formatter, value, error_text, method) {
var val = value,
ok = true,
msg = null;
try {
if (method === 'format') {
val = formatter.format(val);
} else {
val = formatter.parse(val);
}
} catch (e) {
if (e.reason !== method) throw e;
ok = false;
value = e.value;
msg = e.message || error_text;
}
return {
ok: ok,
value: val,
message: msg
};
}
function format_core(formatter, value, error_text, method) {
if (!formatter) return { ok: true, value: value };
if (lang.isArray(value)) {
var res = {
ok: true,
value: [],
messages: []
};
for (var i=0, l=value.length; i<l; i++) {
var single_res = format_single(formatter, value[i], error_text, method);
res.ok = res.ok && single_res.ok;
res.value[i] =single_res.value;
res.messages[i] = single_res.message;
if (!res.ok) {
if (l > 1) res.message = error_text;
else res.message = res.messages[0];
}
}
return res;
} else {
return format_single(formatter, value, error_text, method);
}
}
function format(formatter, value, error_text) {
var err = error_text || text.get('@i18n:widget.validation.format');
return format_core(formatter, value, err, 'format');
}
function parse(formatter, value, error_text) {
var err = error_text || text.get('@i18n:widget.validation.parse');
return format_core(formatter, value, err, 'parse');
}
function normalize_value(value) {
if (!(value instanceof Array)) {
value = value !== undefined ? [value] : [];
}
return value;
}
function emit_delayed(target, type, event, delay) {
delay = delay || 0;
window.setTimeout(function() {
target.emit(type, event);
}, 0);
}
function beautify_message(message) {
var els = [];
var lines = message.split(/\n/g);
var line_span;
for (var i=0,l=lines.length; i<l; i++) {
if (lines[i].charAt(0) == '\t') {
line_span = $('<p />', {
'class': 'error-message-hinted',
text: lines[i].substr(1)
});
els.push(line_span);
} else {
line_span = $('<p />', {
text: lines[i]
});
els.push(line_span);
}
}
return els;
}
function get_val_from_dn(dn, pos) {
if (!dn) return '';
pos = pos === undefined ? 0 : pos;
var val = dn.split(',')[pos].split('=')[1];
return val;
}
/**
* Module with utility functions
* @class
* @singleton
*/
var util = {
/**
* Checks if two variables have equal value
*
* - `string`, `number`, `function`, `boolean`, `null`,
* `undefined` are compared with strict equality
* - 'object' and arrays are compared by values
*
* Available options:
*
* - `unordered` - boolean, sort arrays before value comparison. Does
* not modify original values.
* - `comparator`- function(a,b), returns bool - custom object comparator
*
* @param {Mixed} a
* @param {Mixed} b
* @param {String[]} [options]
* @return {boolean} `a` and `b` are value-equal
*/
equals: equals,
/**
* Check if value is empty.
*
* True when:
*
* - value is undefined or `null` or `''`
* - value is empty Array
* - value is Array with an empty string (`''`)
* - value is empty Object- `{}`
* @param value - value to check
* @return {boolean}
*/
is_empty: is_empty,
/**
* Special kind of negative `equals` where variants of `empty_value` are
* considered same.
*
* @param {Mixed} value New value
* @param {Mixed} pristine Pristine value
* @param {String[]} [options] control options, same as in `equals`
* @return {boolean} `value` and `pristine` differs
*/
dirty: dirty,
/**
* Format value or values using a formatter
*
* Output format for single values:
*
* {
* ok: true|false,
* value: null | formatted value,
* message: null | string
* }
*
* Output form for array:
*
* {
* ok: true|false,
* value: array of formatted values,
* messages: array of error messages
* message: null | string
* }
*
* @param {IPA.formatter} formatter
* @param {Mixed} value
* @param {string} error Default error message
* @return {Object}
*/
format: format,
/**
* Basically the same as format method, just uses formatter's `parse`
* method instead of `format` method.
*
* @param {IPA.formatter} formatter
* @param {Mixed} value
* @param {string} error Default error message
* @return {Object}
*/
parse: parse,
/**
* Encapsulates value into array if it's not already an array.
*
* @param {Mixed} value
* @returns {Array} normalized value
*/
normalize_value: normalize_value,
/**
* Emit delayed event
*
* Uses timer in order to wait for current processing to finish.
*
* @param {Evented} object Source object which emits the event
* @param {String} type Name of the event to emit
* @param {Object} event Event object
* @param {Number} [delay=0]
*/
emit_delayed: emit_delayed,
/**
* Beautify message
*
* Converts text value into array of HTML <p> elements. One additional
* paragraph for each line break.
*
* Multi-lined text may contain TAB character as first char of the line
* to hint at marking the whole line differently.
* @param {string} text
* @return {Array} array of jQuery elements
*/
beautify_message: beautify_message,
/**
* Return value of part of DN on specified position
* @param {string} dn Distinguished name
* @param {Number} [position=0] Zero-based DN part position
* @return {string}
*/
get_val_from_dn: get_val_from_dn
};
return util;
});

View File

@@ -0,0 +1,842 @@
//
// Copyright (C) 2017 FreeIPA Contributors see COPYING for license
//
define([
'dojo/on',
'./ipa',
'./jquery',
'./phases',
'./menu',
'./rpc',
'./reg',
'./text',
'./widget'],
function(on, IPA, $, phases, menu, rpc, reg, text, widget) {
/**
* Vault module
* @class vault
* @alternateClassName IPA.vault
* @singleton
*/
var vault = IPA.vault = {
search_facet_group: {
name: 'vaults',
facets: {
vault_search: 'vault_search',
user_search: 'vault_user_search',
service_search: 'vault_service_search',
shared_search: 'vault_shared_search',
vaultconfig_details: 'vaultconfig_details'
}
}
};
/**
* Create general specification of "* Vaults" details facets.
*/
var make_vaults_details_page_spec = function() {
return {
$type: 'details',
$factory: vault.custom_details_facet,
update_command_name: 'mod_internal',
disable_facet_tabs: true,
sections: [
{
name: 'global_info',
layout_ccs_class: 'col-sm-12',
fields: [
'cn',
'description',
{
name: 'ipavaulttype',
read_only: true
},
{
$type: 'text',
name: 'ipavaultsalt',
visible: false
},
{
$type: 'pub_key',
name: 'ipavaultpublickey',
visible: false
}
]
},
{
$factory: IPA.section,
name: 'divider',
layout_css_class: 'col-sm-12',
fields: []
},
{
$factory: IPA.section,
name: 'members',
label: '@i18n:objects.vault.members',
fields: [
{
$type: 'association_table',
id: 'member_user_cn',
name: 'member_user',
acl_param: 'member',
columns: [
{
name: 'member_user',
label: '@i18n:objects.vault.user'
}
]
},
{
$type: 'association_table',
id: 'member_group_cn',
name: 'member_group',
other_entity: 'group',
acl_param: 'member',
columns: [
{
name: 'member_group',
label: '@i18n:objects.vault.group'
}
]
},
{
$type: 'association_table',
id: 'member_service_cn',
name: 'member_service',
other_entity: 'service',
other_option_name: 'services',
acl_param: 'member',
columns: [
{
name: 'member_service',
label: '@i18n:objects.vault.service'
}
]
}
]
},
{
$factory: IPA.section,
name: 'owners',
label: '@i18n:objects.vault.owners',
fields: [
{
$type: 'association_table',
id: 'owner_user_cn',
name: 'owner_user',
add_method: 'add_owner',
remove_method: 'remove_owner',
other_entity: 'user',
acl_param: 'owner',
columns: [
{
name: 'owner_user',
label: '@i18n:objects.vault.user'
}
]
},
{
$type: 'association_table',
id: 'owner_group_cn',
name: 'owner_group',
add_method: 'add_owner',
remove_method: 'remove_owner',
other_entity: 'group',
acl_param: 'owner',
columns: [
{
name: 'owner_group',
label: '@i18n:objects.vault.group'
}
]
},
{
$type: 'association_table',
id: 'owner_service_cn',
name: 'owner_service',
add_method: 'add_owner',
remove_method: 'remove_owner',
other_entity: 'service',
other_option_name: 'services',
acl_param: 'owner',
columns: [
{
name: 'owner_service',
label: '@i18n:objects.vault.service'
}
]
}
]
}
]
};
};
/**
* Create entity spec for whole vaults and also spec for search facet, adder
* and deleter dialog.
*/
var make_my_vault_spec = function() {
var entity = {
name: 'vault',
facets: [
{
$type: 'search',
tab_label: '@i18n:objects.vault.my_vaults_title',
facet_groups: [vault.search_facet_group],
facet_group: 'vaults',
disable_facet_tabs: false,
search_all_entries: true,
tabs_in_sidebar: true,
custom_actions: [
{
$type: 'add',
hide_cond: []
},
{
$type: 'batch_remove',
hide_cond: []
}
],
columns: [
'cn',
'ipavaulttype'
],
policies: [
vault.config_sidebar_policy
]
}
],
adder_dialog: {
$factory: vault.custom_adder_dialog,
name: 'add',
method: 'add_internal',
policies: [
{ $factory: vault.adder_policy }
]
},
deleter_dialog: {
// Each parametr is present only in one facet. It could cause errors
// in case that table on each facet gather more columns with these names.
// I.e. facet with user vaults get column with name 'service', then
// the value of 'service' column will be also added to command options.
additional_table_attrs: ['username', 'service', 'shared']
}
};
/**
* This function extends general details facet - so the same declaration
* of facet (which would differ only in several lines)
* should not be present six times.
*/
var update_facet_spec = function(facet, facet_type) {
facet.sections[0].fields.push(facet_type);
facet.refresh_attribute = facet_type;
facet.update_attribute = facet_type;
var user_members = facet.sections[2].fields[0];
var group_members = facet.sections[2].fields[1];
var service_members = facet.sections[2].fields[2];
var user_owners = facet.sections[3].fields[0];
var group_owners = facet.sections[3].fields[1];
var service_owners = facet.sections[3].fields[2];
var attributes = {
refresh_attribute: facet_type,
additional_add_del_field: facet_type
};
$.extend(user_members, attributes);
$.extend(user_owners, attributes);
$.extend(group_members, attributes);
$.extend(group_owners, attributes);
$.extend(service_members, attributes);
$.extend(service_owners, attributes);
};
// Create details page for my vauls:
var details_spec = make_vaults_details_page_spec();
entity.facets.push(details_spec);
// Create details page for user vaults and modify it
details_spec = make_vaults_details_page_spec();
details_spec.name = 'vault_user';
update_facet_spec(details_spec, 'username');
details_spec.redirect_info = {
facet: 'user_search'
};
entity.facets.push(details_spec);
// Create details page for service vaults and modify it
details_spec = make_vaults_details_page_spec();
details_spec.name = 'vault_service';
update_facet_spec(details_spec, 'service');
details_spec.redirect_info = {
facet: 'service_search'
};
entity.facets.push(details_spec);
// Create details page for shared vaults and modify it
details_spec = make_vaults_details_page_spec();
details_spec.name = 'vault_shared';
update_facet_spec(details_spec, 'shared');
details_spec.redirect_info = {
facet: 'shared_search'
};
entity.facets.push(details_spec);
return entity;
};
vault.custom_details_facet = function(spec) {
spec = spec || {};
var that = IPA.details_facet(spec);
that.load = function(data) {
that.details_facet_load(data);
// show fields according to the type of vault
var type_f = that.fields.get_field('ipavaulttype');
var type = type_f.value[0];
var salt_w = that.fields.get_field('ipavaultsalt').widget;
var pub_key_w = that.fields.get_field('ipavaultpublickey').widget;
if (type === 'symmetric') {
pub_key_w.set_visible(false);
salt_w.set_visible(true);
} else if (type === 'asymmetric') {
pub_key_w.set_visible(true);
salt_w.set_visible(false);
} else {
pub_key_w.set_visible(false);
salt_w.set_visible(false);
}
};
return that;
};
vault.public_key_widget = function(spec) {
spec = spec || {};
var that = IPA.sshkey_widget(spec);
that.set_user_value = function(value) {
var previous = that.key;
that.key = value;
that.update_link();
if (value !== previous) {
that.value_changed.notify([], that);
that.emit('value-change', { source: that });
}
};
that.update = function(value) {
var key = value[0];
if (key) that.key = key;
if (that.key && that.key !== '') {
that.originally_set = true;
that.original_key = that.key;
}
that.update_link();
that.on_value_changed(value);
};
that.get_status = function() {
var status = '';
var value = that.key;
if (that.original_key) {
if (value !== that.original_key) {
if (value === '') {
status = text.get('@i18n:objects.publickey.status_mod_ns');
} else {
status = text.get('@i18n:objects.publickey.status_mod_s');
}
} else {
// f00c is code of check icon
var decimal_check_i = parseInt('f00c', 16);
status = String.fromCharCode(decimal_check_i);
}
} else {
status = text.get('@i18n:objects.publickey.status_new_ns');
}
return status;
};
that.create_edit_dialog = function() {
var writable = that.is_writable();
var dialog = IPA.dialog({
name: 'pubkey-edit-dialog',
title: '@i18n:objects.publickey.set_dialog_title',
width: 500,
height: 380
});
dialog.message = text.get('@i18n:objects.publickey.set_dialog_help');
dialog.create_button({
name: 'update',
label: '@i18n:buttons.set',
click: function() {
var value = dialog.textarea.val();
that.set_user_value(value);
dialog.close();
}
});
dialog.create_button({
name: 'cancel',
label: '@i18n:buttons.cancel',
click: function() {
dialog.close();
}
});
dialog.create_content = function() {
dialog.container.append(dialog.message);
dialog.textarea = $('<textarea/>', {
'class': 'certificate',
disabled: !that.enabled
}).appendTo(dialog.container);
var key = that.key || '';
dialog.textarea.val(key);
};
return dialog;
};
return that;
};
/**
* Adder policy handles realtime showing and hiding fields when user switch
* between User/Service/Shared vault in adder dialog.
*
* @extends IPA.facet_policy
*/
vault.adder_policy = function(spec) {
var that = IPA.facet_policy(spec);
that.init = function() {
var type_f = that.container.fields.get_field('type');
on(type_f, 'value-change', that.on_type_change);
};
that.on_type_change = function() {
var type_f = that.container.fields.get_field('type');
var user_f = that.container.fields.get_field('username');
var service_f = that.container.fields.get_field('service');
var mode = type_f.get_value()[0];
var user = true;
var service = true;
if (mode === 'user') service = false;
else if (mode === 'service') user = false;
else if (mode === 'shared') user = service = false;
user_f.set_enabled(user);
user_f.widget.set_visible(user);
service_f.set_enabled(service);
service_f.widget.set_visible(service);
};
return that;
};
/**
* Custom adder dialog.
*
* @extends IPA.entity_adder_dialog
*/
vault.custom_adder_dialog = function(spec) {
spec = spec || {};
spec.sections = spec.sections || [];
var section_warn_arch_ret= {
show_header: false,
name: 'warning_ar',
fields: [
{
field: false,
$type: 'html',
name: 'warn_arch_ret'
}
],
layout: {
$factory: widget.fluid_layout,
widget_cls: "col-sm-12 controls",
label_cls: "hide"
}
};
var section_f = {
show_header: false,
fields: [
{
$type: 'radio',
name: 'type',
flags: ['no_command'],
label: '@i18n:objects.vault.type',
options: [
{
value: 'user',
label: '@i18n:objects.vault.user'
},
{
value: 'service',
label: '@i18n:objects.vault.service'
},
{
value: 'shared',
label: '@i18n:objects.vault.shared'
}
]
},
{
$type: 'entity_select',
name: 'username',
other_entity: 'user',
other_field: 'uid'
},
{
$type: 'entity_select',
name: 'service',
other_entity: 'service',
other_field: 'krbprincipalname'
},
'cn',
'description',
{
$type: 'radio',
name: 'ipavaulttype',
default_value: 'standard',
read_only: true,
options: [
{
value: 'standard',
label: '@i18n:objects.vault.standard_type'
},
{
label: '@i18n:objects.vault.symmetric_type'
},
{
label: '@i18n:objects.vault.asymmetric_type'
}
],
tooltip: "@i18n:objects.vault.type_tooltip"
}
]
};
var section_warn_standard = {
name: 'warning_st',
fields: [
{
field: false,
$type: 'html',
name: 'warn_standard'
}
],
layout: {
$factory: widget.fluid_layout,
widget_cls: "col-sm-12 controls",
label_cls: "hide"
}
};
spec.sections.push(section_warn_arch_ret);
spec.sections.push(section_f);
spec.sections.push(section_warn_standard);
var that = IPA.entity_adder_dialog(spec);
that.create_add_command = function(record) {
var command = that.entity_adder_dialog_create_add_command(record);
var type_f = that.fields.get_field('type');
var type = type_f.save()[0];
if (type === 'shared') command.set_option(type, true);
return command;
};
that.create_content = function() {
var warn_arch_ret_w = that.widgets.get_widget('warning_ar.warn_arch_ret');
var warn_st_w = that.widgets.get_widget('warning_st.warn_standard');
var warn_arch_text = text.get('@i18n:objects.vault.add_warn_arch_ret');
var warn_st_text = text.get('@i18n:objects.vault.add_warn_standard');
var warn_arch_ret = IPA.alert_helper.create_alert('arch', warn_arch_text);
var warn_standard = IPA.alert_helper.create_alert('standard',
warn_st_text);
warn_st_w.html = IPA.alert_helper.render_alert(warn_standard);
warn_arch_ret_w.html = IPA.alert_helper.render_alert(warn_arch_ret);
that.entity_adder_dialog_create_content();
var facet_name = that.entity.facet.name;
facet_name = facet_name.substr(0, facet_name.indexOf('_'));
if (facet_name === "") facet_name = 'user';
var type_f = that.fields.get_field('type');
type_f.set_pristine_value([facet_name]);
if (IPA.is_selfservice) type_f.set_writable(false);
};
that.on_success = function(data) {
var result = data.result.result;
var my_vaults = that.entity.get_facet('search');
function update_facet(name) {
var fa = that.entity.get_facet(name);
fa.set_expired_flag();
}
if (result.service) {
update_facet('service_search');
} else if (result.shared) {
update_facet('shared_search');
} else {
update_facet('user_search');
my_vaults.set_expired_flag();
}
};
that.added.attach(that.on_success);
return that;
};
/**
* Creates specification of search facet for User Vaults
*/
var make_user_vault_search_spec = function() {
return {
$type: 'search',
entity: 'vault',
managed_entity: 'vault',
name: 'user_search',
tab_label: '@i18n:objects.vault.user_vaults_title',
label: '@i18n:objects.vault.user_vaults_title',
facet_groups: [vault.search_facet_group],
facet_group: 'vaults',
custom_actions: [
{
$type: 'add',
hide_cond: []
},
{
$type: 'batch_remove',
hide_cond: []
}
],
additional_navigation_arguments: ['username'],
show_values_with_dup_key: true,
details_facet: 'vault_user',
show_command_additional_attr: 'username',
disable_facet_tabs: false,
tabs_in_sidebar: true,
command_options: {
'users': true
},
columns: [
'cn',
'username',
'ipavaulttype'
],
policies: [
vault.config_sidebar_policy
]
};
};
var make_service_vault_spec = function() {
return {
$type: 'search',
entity: 'vault',
managed_entity: 'vault',
name: 'service_search',
tab_label: '@i18n:objects.vault.service_vaults_title',
label: '@i18n:objects.vault.service_vaults_title',
facet_groups: [vault.search_facet_group],
facet_group: 'vaults',
additional_navigation_arguments: ['service'],
show_values_with_dup_key: true,
details_facet: 'vault_service',
show_command_additional_attr: 'service',
disable_facet_tabs: false,
tabs_in_sidebar: true,
command_options: {
'services': true
},
columns: [
'cn',
'service',
'ipavaulttype'
],
policies: [
vault.config_sidebar_policy
]
};
};
var make_shared_vault_spec = function() {
return {
$type: 'search',
entity: 'vault',
managed_entity: 'vault',
tab_label: '@i18n:objects.vault.shared_vaults_title',
name: 'shared_search',
label: '@i18n:objects.vault.shared_vaults_title',
facet_groups: [vault.search_facet_group],
facet_group: 'vaults',
additional_navigation_arguments: ['shared'],
show_values_with_dup_key: true,
show_command_additional_attr: 'shared',
details_facet: 'vault_shared',
disable_facet_tabs: false,
tabs_in_sidebar: true,
command_options: {
'shared': true
},
columns: [
'cn',
'shared',
'ipavaulttype'
],
policies: [
vault.config_sidebar_policy
]
};
};
var make_vaultconfig_spec = function() {
return {
name: 'vaultconfig',
facets: [
{
$type: 'details',
label: '@i18n:objects.vault.config_title',
tab_label: '@i18n:objects.vault.config_title',
facet_groups: [vault.search_facet_group],
facet_group: 'vaults',
disable_facet_tabs: false,
tabs_in_sidebar: true,
check_rights: false,
no_update: true,
fields: [
{
$type: "multivalued",
name: 'kra_server_server'
},
{
$type: 'textarea',
name: 'transport_cert',
read_only: true,
style: {
width: '550px',
height: '350px'
}
}
],
policies: [
vault.config_sidebar_policy
]
}
]
};
};
vault.config_sidebar_policy = function(spec) {
var that = IPA.facet_policy(spec);
that.post_create = function(data) {
if (IPA.is_selfservice && that.container &&
that.container.tabs_in_sidebar) {
var header = that.container.header;
if (header) header.tabs_widget.hide_tab('vaultconfig_details');
}
};
return that;
};
vault.remove_vault_menu_item = function() {
if (IPA.vault_enabled) return;
var menu_location = IPA.is_selfservice ? 'vault' : 'network_services/vault';
menu.remove_item(menu_location);
};
vault.my_vault_spec = make_my_vault_spec();
vault.user_vault_search_spec = make_user_vault_search_spec();
vault.service_vault_spec = make_service_vault_spec();
vault.shared_vault_spec = make_shared_vault_spec();
vault.vaultconfig_spec = make_vaultconfig_spec();
vault.register = function() {
var e = reg.entity;
var fa = reg.facet;
var w = reg.widget;
w.register('pub_key', vault.public_key_widget);
e.register({type: 'vault', spec: vault.my_vault_spec});
e.register({type: 'vaultconfig', spec: vault.vaultconfig_spec});
fa.register_from_spec('vault_user_search', vault.user_vault_search_spec);
fa.register_from_spec('vault_service_search', vault.service_vault_spec);
fa.register_from_spec('vault_shared_search', vault.shared_vault_spec);
};
phases.on('registration', vault.register);
phases.on('profile', vault.remove_vault_menu_item, 20);
return vault;
});

Some files were not shown because too many files have changed in this diff Show More