def get_item_infos(self): """ Returns all configurable items including information about type etc. :return dict: """ infos = { "backend.index": { "type": "boolean", "title": N_("Indexing") }, "gui.debug": { "type": "boolean", "title": N_("Debug mode") }, "logger_gosa.level": { "options": ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], "title": N_("Log level") }, "formatter_console.format": { "type": "string", "title": N_("Log format") } } # populate values for path in infos: infos[path]['value'] = self.get(path) return infos
def process(self, all_props, key, value, objectType, attribute, comp=None): errors = [] index = PluginRegistry.getInstance("ObjectIndex") factory = ObjectFactory.getInstance() query = {attribute: ""} if factory.isBaseType(objectType): query["_type"] = objectType else: query["extension"] = objectType for val in value: if val in all_props[key]['value']: # do not check existing values continue in_creation = False for obj in index.currently_in_creation: if hasattr(obj, attribute) and val == getattr(obj, attribute) and objectType == obj.get_type(): # this object has been created but is not in the DB yet in_creation = True break if in_creation is True: continue query[attribute] = val if not len(index.search(query, {'dn': 1})): errors.append(dict(index=value.index(val), detail=N_("no '%(type)s' object with '%(attribute)s' property matching '%(value)s' found"), type=objectType, attribute=attribute, value=val)) return len(errors) == 0, errors
class Transliterate(Plugin): _target_ = 'misc' @Command(__help__=N_("Transliterate a given string")) def transliterate(self, string): """ Deliver a plain ASCII value of the given string by additionally replacing a couple of known characters by their ASCII versions. ========= ========================= Parameter Description ========= ========================= string String to be ASCIIfied ========= ========================= ``Return:`` ASCII string """ table = { ord(u'ä'): u'ae', ord(u'ö'): u'oe', ord(u'ü'): u'ue', ord(u'Ä'): u'Ae', ord(u'Ö'): u'Oe', ord(u'Ü'): u'Ue', } string = string.translate(table) return unidecode(string)
def process(self, all_props, key, value): errors = [] if value is None or len(value) == 0: return True, [] for index, val in enumerate(value): lines = val.split("\n") if len(lines) == 0: return len(errors) == 0, errors shebang = lines[0] m = re.search("#!\/(usr\/)?bin\/([^\s]+)\s?(.+)?", shebang) if m: binary = m.group(3) if m.group(2) == "env" else m.group(2) if binary[0:6] == "python": version = int(binary[6:]) if len(binary) > 6 else 2 linter = PyLint() return linter.process(all_props, key, [val], version=version, idx=index) elif binary == "bash": linter = ShellLint() return linter.process(all_props, key, [val], idx=index) else: logging.getLogger(__name__).warning( "no linter found for %s" % binary) else: errors.append( dict(index=index, detail=N_("invalid shebang line"))) return len(errors) == 0, errors
def createAddGroupIfNotExists(self, user_dn, user_name, gid_number): if user_dn is None or user_name is None or gid_number is None: return index = PluginRegistry.getInstance("ObjectIndex") res = index.search({ "_type": "PosixGroup", "gidNumber": gid_number }, {"dn": 1}) if len(res) == 0: # create group user = ObjectProxy(user_dn) group = ObjectProxy(user.get_adjusted_parent_dn(), "PosixGroup") group.cn = user_name group.description = N_("Group of user %s" % user_name) group.autoGid = False group.gidNumber = gid_number group.memberUid = [user_name] group.commit() elif len(res) == 1: group = ObjectProxy(res[0]["dn"]) if user_name not in group.memberUid: group.memberUid.append(user_name) group.commit() else: raise GosaException( C.make_error('GROUP_ID_IS_AMBIGUOUS', gid=gid_number))
def discover(self): print(N_("Searching for service provider...")) svcs = find_api_service() if svcs: return svcs[0] return None
class ShellSupport(Plugin): """ Section **posix** +------------------+------------+-------------------------------------------------------------+ + Key | Format + Description | +==================+============+=============================================================+ + shells | String + Path to a file containing one shell perl line. | +------------------+------------+-------------------------------------------------------------+ """ _target_ = 'misc' def __init__(self): self.__shells = {} # Use a shell source file env = Environment.getInstance() source = env.config.get('posix.shells', default="/etc/shells") with open(source) as f: self.__shells = list( filter(lambda y: not y.startswith("#"), [x.strip() for x in f.read().split("\n")])) @Command(__help__=N_("Return list of supported shells")) def getShellList(self): """ Deliver a list of supported shells. ``Return:`` List """ return self.__shells
def render(data): overlay = {} tooltip = None if "status" in data and data["status"] is not None: status = data["status"][0] if status == "warning": overlay["color"] = '#F6BB42' overlay["icon"] = "@Ligature/help" tooltip = N_("Warning") elif status in ["error", "token-expired"]: overlay["color"] = '#ED5565' overlay["icon"] = "@Ligature/help" tooltip = N_("Error") if status == "error" else N_("Token expired") elif status == "pending": tooltip = N_("Pending installation") overlay["color"] = "#AAB2BD" overlay["icon"] = "@Ligature/help" elif status == "install": tooltip = N_("Installing") overlay["color"] = "#AAB2BD" overlay["icon"] = "@Ligature/sync" elif status in ["ready", "discovered"]: overlay["color"] = "#8CC152" overlay["icon"] = "@Ligature/check" tooltip = N_("Ready") if status == "ready" else N_("Discovered") res = {"icon": "@Ligature/pc"} if "icon" in overlay: res["overlay"] = overlay if tooltip is not None: res["tooltip"] = tooltip return res
class UploadManager(Plugin): _priority_ = 0 _target_ = "core" __tmp_paths = {} __upload_handlers = {} def __init__(self): self.env = Environment.getInstance() self.log = logging.getLogger(__name__) self.log.info("initializing upload manager") def serve(self): sched = PluginRegistry.getInstance("SchedulerService").getScheduler() sched.add_interval_job(self.__gc, minutes=10, tag='_internal', jobstore="ram") # register upload handlers for entry in pkg_resources.iter_entry_points("gosa.upload_handler"): module = entry.load() self.__upload_handlers[entry.name] = module() @Command(needsUser=True, needsSession=True, __help__=N_("Registers a temporary upload path")) def registerUploadPath(self, user, session_id, type): uuid = str(uuid4()) self.__tmp_paths[uuid] = { 'user': user, 'session_id': session_id, 'type': type, 'valid_until': datetime.datetime.now() + datetime.timedelta(minutes=10) } return uuid, "/uploads/%s" % uuid def get_path_settings(self, uuid): return self.__tmp_paths[uuid] if uuid in self.__tmp_paths else None def unregisterUploadPath(self, uuid): if uuid in self.__tmp_paths: del self.__tmp_paths[uuid] return True else: return False def get_upload_handler(self, type): return self.__upload_handlers[ type] if type in self.__upload_handlers else None def __gc(self): for uuid in list(self.__tmp_paths): if self.__tmp_paths[uuid]['valid_until'] < datetime.datetime.now(): # outdated del self.__tmp_paths[uuid]
def process(self, all_props, key, value): errors = [] if "sambaSID" in all_props and len(all_props["sambaSID"]["value"]): sid = all_props["sambaSID"]["value"][0] if sid in value: errors.append( dict(index=value.index(sid), detail=N_("recursive nesting not allowed"))) return len(errors) == 0, errors
def process(self, all_props, key, value): errors = [] for hostname in value: if not re.match("^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$", hostname): errors.append(dict(index=value.index(hostname), detail=N_("invalid hostname '%(hostname)s'"), hostname=hostname)) return len(errors) == 0, errors
def process(self, all_props, key, value, objectType): errors = [] index = PluginRegistry.getInstance("ObjectIndex") for dn in value: if not len(index.search({'_type': objectType, 'dn': dn}, {'dn': 1})): errors.append(dict(index=value.index(dn), detail=N_("DN '%(dn)s' does not exist"), dn=dn)) return len(errors) == 0, errors
def process(self, all_props, key, value, match): errors = [] # All items of value have to match. cnt = 0 for item in value: if not re.match(match, item): errors.append(dict(index=cnt, detail=N_("syntax error"))) return False, errors cnt += 1 return True, errors
def process(self, all_props, key, value, max_types): errors = [] res = self.__get_types(value) if len(res) > int(max_types): errors.append(dict(index=0, detail=N_("Too many types '%(types)s'. Only '%(allowed)s' types allowed."), allowed=max_types, types=res)) return len(errors) == 0, errors
def process(self, all_props, key, value, minSize, maxSize): errors = [] # Convert limits to integer values. minSize = int(minSize) maxSize = int(maxSize) # Each item of value has to match the given length-rules for entry in value: cnt = len(entry) if minSize >= 0 and cnt < minSize: errors.append(dict(index=cnt, detail=N_("value is short, at least %(count)s characters required"), count=minSize)) return False, errors elif 0 <= maxSize < cnt: errors.append(dict(index=cnt, detail=N_("value is long, at max %(count)s characters allowed"), count=maxSize)) return False, errors return True, errors
def process(self, all_props, key, value): errors = [] # Each item of value has to match the given length-rules for idx, entry in enumerate(value): try: loads(entry) except Exception as e: errors.append(dict(index=idx, detail=N_("value is no valid JSON string: '%(error)s'"), error=str(e))) return True, errors
def process(self, all_props, key, value, match, case_ignore=False): errors = [] # Check each property value cnt = 0 for item in value: # Depending on the ignore-case parameter we do not match upper/lower-case differences. if case_ignore: if item.lower() != match.lower(): errors.append(dict(index=cnt, detail=N_("item does not match the given value ignoring the case", ))) return False, errors else: if item != match: errors.append(dict(index=cnt, detail=N_("item does not match the given value", ))) return False, errors cnt += 1 return True, errors
def process(self, all_props, key, value): domain = value[0] errors = [] index = PluginRegistry.getInstance("ObjectIndex") res = index.search({'_type': 'SambaDomain', 'sambaDomainName': domain}, {'_uuid': 1}) if len(res): return True, errors errors.append(dict(index=0, detail=N_("Unknown domain '%(domain)s'"), domain=value[0])) return False, errors
def process(self, all_props, key, value, match): errors = [] # All items of value have to match. cnt = 0 for item in value: if difflib.SequenceMatcher(None, item, match).ratio() < 0.75: errors.append(dict(index=cnt, detail=N_("value is not like %(comparator)s"), comparator=match)) return False, errors cnt += 1 return True, errors
def process(self, all_props, key, value): errors = [] # All items of value have to match. cnt = 0 for item in value: spec = urlparse(item) if not spec.scheme in ["http", "https"]: errors.append(dict(index=cnt, detail=N_("invalid HTTP URL"))) return False, errors cnt += 1 return True, errors
def process(self, all_props, key, value): errors = [] index = PluginRegistry.getInstance("ObjectIndex") for dn in value: if dn not in all_props[key]['value']: # do not check existing values continue if not len(index.search({'dn': dn}, {'dn': 1})): errors.append( dict(index=value.index(dn), detail=N_("DN '%(dn)s' does not exist"), dn=dn)) return len(errors) == 0, errors
def process(self, all_props, key, value, type, attribute, attribute_content): errors = [] if key == "extension": # extension validation mode, use value from props value = all_props[attribute]["value"] if len(value) == 0: errors.append(dict(index=0, detail=N_("Object has no member of type '%(type)s'."), type=type)) else: index = PluginRegistry.getInstance("ObjectIndex") query = {attribute_content: {"in_": value}} if ObjectFactory.getInstance().isBaseType(type): query["_type"] = type else: query["extension"] = type res = index.search(query, {"dn": 1}) if len(res) > 0: return len(errors) == 0, errors if len(index.currently_in_creation) > 0: # check if the referenced object we are looking for is currently being created found_types = [x.__class__.__name__ for x in index.currently_in_creation if getattr(x, attribute_content) in value] if type in found_types: return True, errors if self.traverse_groups(value, type, attribute, attribute_content): # found type in subgroup member return True, errors errors.append(dict(index=0, detail=N_("Object has no member of type '%(type)s'."), type=type)) return len(errors) == 0, errors
class RpcPlugin(Plugin): _target_ = 'gui' _priority_ = 80 @Command(__help__=N_("Returns manifest informations from all uploaded dashboard widgets.")) def getDashboardWidgets(self): plugins = [] #TODO: wrong path, needs to be configurable for root, dirs, files in os.walk(os.path.join(frontend_path, 'gosa', 'uploads', 'widgets')): for d in dirs: manifest_path = os.path.join(root, d, "Manifest.json") if os.path.exists(manifest_path): with open(manifest_path) as f: plugin_data = loads(f.read()) plugins.append(plugin_data) return plugins
def get_submenu(self, entries): result = None for entry in entries: if result is None: result = {'apps': {}} if 'children' in entry: if not 'menus' in result: result['menus'] = {} result['menus'][entry.get('name', N_('Unbekannt'))] = self.get_submenu( entry['children']) else: application = self.get_application(entry) result['apps'][application.get('cn', 'name')] = application return result
def process(self, all_props, key, value): errors = [] index = PluginRegistry.getInstance("ObjectIndex") for dn in value: # do not check dn's that are currently being moved to if index.is_currently_moving(dn, move_target=True): continue if dn in all_props[key]['value']: # do not check existing values continue if not len(index.search({'dn': dn}, {'dn': 1})): errors.append(dict(index=value.index(dn), detail=N_("DN '%(dn)s' does not exist"), dn=dn)) return len(errors) == 0, errors
def process(self, all_props, key, value, object): errors = [] # special case for own dn in member -> skip validation if key == "member" and object.dn in value: return True, errors # collect all conditions that are related to this attribute key and whose extension is active conditions = [(name, x) for name, x in object.extension_conditions.items() if key in x["properties"] and object.parent.is_extended_by(name)] props_copy = copy.deepcopy(object.myProperties) for extension_name, condition in conditions: res, errs = object.processValidator(condition, key, value, props_copy) if not res: errors.append(dict(code='OBJECT_EXTENSION_NOT_ALLOWED', detail=N_("Object is extended by '%(extension)s', which is not allowed. Reason: '%(error)s'"), extension=extension_name, error=", ".join([x["detail"] % x for x in errs]))) return len(errors) == 0, errors
def process(self, all_props, key, value, match): errors = [] # All items of value have to match. cnt = 0 match = int(match) for item in value: # Number or attribute? if isinstance(item, int) or item.isdigit(): item = int(item) else: item = int(all_props[item]["value"][0]) if not (item > match): errors.append(dict(index=cnt, detail=N_("item needs to be greater than %(compare)s"), compare=match )) return False, errors cnt += 1 return True, errors
class ZarafaRPCMethods(Plugin): _target_ = 'gui' _priority_ = 80 @Command( __help__=N_("Returns a list with all selectable zarafa mail servers")) def getZarafaMailServers(self): index = PluginRegistry.getInstance("ObjectIndex") res = index.search( { 'extension': 'ZarafaServer', 'zarafaAccount': 'True' }, { 'cn': 1, 'zarafaAccount': 1 }) res = list(set([x['cn'][0] for x in res])) res.sort() return res
def _handleNotification(cls, data, channel): data = data.Notification title = N_("System notification") icon = "dialog-information" timeout = 10000 if hasattr(data, 'Title'): title = data.Title.text if hasattr(data, 'Icon'): icon = data.Icon.text if hasattr(data, 'Timeout'): timeout = int(data.Timeout.text) SseHandler.send_message( { "title": title, "body": data.Body.text, "icon": icon, "timeout": timeout }, topic="notification", channel=channel)
class Gravatar(Plugin): """ Utility class that contains methods needed to retrieve gravatar URLs. """ _target_ = 'gravatar' def __init__(self): env = Environment.getInstance() self.env = env @Command(__help__=N_( "Generate the gravatar URL for the given mail address and size.")) def getGravatarURL(self, mail, size=40, url="http://www.gonicus.de"): """ Generate the gravatar URL to be used for user pictures on demand. ========= ====================================== Parameter Description ========= ====================================== mail Gravatar's mail address size desired image size url Clickable URL ========= ====================================== ``Return:`` Image URL """ gravatar_url = "http://www.gravatar.com/avatar.php?" gravatar_url += urllib.parse.urlencode({ 'gravatar_id': hashlib.md5(mail.lower().encode()).hexdigest(), 'default': url, 'size': str(size) }) return gravatar_url