def dispatchObjectMethod(self, user, session_id, ref, method, *args): """ Call a member method of the referenced object. ================= ========================== Parameter Description ================= ========================== ref UUID / object reference method Method name args Arguments to pass to the method ================= ========================== ``Return``: mixed """ objdsc = self.__get_ref(ref) if not objdsc: raise ValueError(C.make_error("REFERENCE_NOT_FOUND", ref=ref)) if not method in objdsc['object']['methods']: raise ValueError(C.make_error("METHOD_NOT_FOUND", method=method)) if not self.__check_user(ref, user): raise ValueError(C.make_error("NOT_OBJECT_OWNER")) return getattr(objdsc['object']['object'], method)(*args)
def __init__(self, response=None, exception=None, method=None): self.exception = exception self.response = response self.method = method if method is not None else "" if response.status_code == 404: self.message = C.make_error('FOREMAN_OBJECT_NOT_FOUND', response.url) else: try: data = response.json() except json.decoder.JSONDecodeError as e: self.message = C.make_error('FOREMAN_COMMUNICATION_ERROR', response.status_code) else: if "error" in data: if "message" in data["error"]: self.message = C.make_error( 'FOREMAN_COMMUNICATION_ERROR', data["error"]["message"]) else: self.message = ", ".join( data["error"]["full_messages"] ) if "full_messages" in data["error"] else str( data["error"]) else: self.message = C.make_error('FOREMAN_COMMUNICATION_ERROR', response.status_code)
def setObjectProperty(self, user, ref, name, value): """ Set a property on an existing stack object. ================= ========================== Parameter Description ================= ========================== ref UUID / object reference name Property name value Property value ================= ========================== """ objdsc = self.__get_ref(ref) if not objdsc: raise ValueError(C.make_error("REFERENCE_NOT_FOUND", ref=ref)) if not name in objdsc['object']['properties']: raise ValueError(C.make_error("PROPERTY_NOT_FOUND", property=name)) details = objdsc['object']['object'].get_attributes(True) if details[name]['auto']: raise ValueError(C.make_error("AUTOGENERATED_ATTRIBUTE")) if not self.__check_user(ref, user): raise ValueError(C.make_error("NOT_OBJECT_OWNER")) objdsc['last_interaction'] = datetime.datetime.now() if 'mark_for_deletion' in objdsc: # as this object has been marked for deletion, we have to run the garbage collection # to remove this mark now self.__gc() return setattr(objdsc['object']['object'], name, value)
def lockAccountPassword(self, user, object_dn): """ Locks the account password for the given DN """ # Do we have read permissions for the requested attribute env = Environment.getInstance() topic = "%s.objects.%s.attributes.%s" % (env.domain, "User", "userPassword") aclresolver = PluginRegistry.getInstance("ACLResolver") if not aclresolver.check(user, topic, "w", base=object_dn): self.__log.debug("user '%s' has insufficient permissions to write %s on %s, required is %s:%s" % ( user, "isLocked", object_dn, topic, "w")) raise ACLException(C.make_error('PERMISSION_ACCESS', topic, target=object_dn)) # Get the object for the given dn user = ObjectProxy(object_dn) # Check if there is a userPasswort available and set if not "userPassword" in user.get_attributes(): raise PasswordException(C.make_error("PASSWORD_NO_ATTRIBUTE")) if not user.userPassword: raise PasswordException(C.make_error("PASSWORD_NOT_AVAILABLE")) # Try to detect the responsible password method-class pwd_o = self.detect_method_by_hash(user.userPassword) if not pwd_o: raise PasswordException(C.make_error("PASSWORD_METHOD_UNKNOWN")) # Lock the hash and save it user.userPassword = pwd_o.lock_account(user.userPassword) user.commit()
def setPasswordRecoveryAnswers(self, user, object_dn, data): """ Set the password recovery answers for a user """ data = loads(data) # Do we have read permissions for the requested attribute env = Environment.getInstance() topic = "%s.objects.%s.attributes.%s" % (env.domain, "User", "passwordRecoveryHash") aclresolver = PluginRegistry.getInstance("ACLResolver") if not aclresolver.check(user, topic, "w", base=object_dn): self.__log.debug("user '%s' has insufficient permissions to write %s on %s, required is %s:%s" % ( user, "isLocked", object_dn, topic, "w")) raise ACLException(C.make_error('PERMISSION_ACCESS', topic, target=object_dn)) user = ObjectProxy(object_dn) method = user.passwordMethod # Try to detect the responsible password method-class pwd_o = self.get_method_by_method_type(method) if not pwd_o: raise PasswordException(C.make_error("PASSWORD_UNKNOWN_HASH", type=method)) # hash the new answers for idx, answer in data.items(): data[idx] = pwd_o.generate_password_hash(self.clean_string(answer), method) print("%s encrypted with %s as index %s => %s" % (self.clean_string(answer), method, idx, data[idx])) # Set the password and commit the changes user.passwordRecoveryHash = dumps(data) user.commit()
def lockAccountPassword(self, user, object_dn): """ Locks the account password for the given DN """ # Do we have read permissions for the requested attribute env = Environment.getInstance() topic = "%s.objects.%s.attributes.%s" % (env.domain, "User", "userPassword") aclresolver = PluginRegistry.getInstance("ACLResolver") if not aclresolver.check(user, topic, "w", base=object_dn): self.__log.debug( "user '%s' has insufficient permissions to write %s on %s, required is %s:%s" % (user, "isLocked", object_dn, topic, "w")) raise ACLException( C.make_error('PERMISSION_ACCESS', topic, target=object_dn)) # Get the object for the given dn user = ObjectProxy(object_dn) # Check if there is a userPasswort available and set if not "userPassword" in user.get_attributes(): raise PasswordException(C.make_error("PASSWORD_NO_ATTRIBUTE")) if not user.userPassword: raise PasswordException(C.make_error("PASSWORD_NOT_AVAILABLE")) # Try to detect the responsible password method-class pwd_o = self.detect_method_by_hash(user.userPassword) if not pwd_o: raise PasswordException(C.make_error("PASSWORD_METHOD_UNKNOWN")) # Lock the hash and save it user.userPassword = pwd_o.lock_account(user.userPassword) user.commit()
def continueObjectEditing(self, user, ref): """ Objects which have been opened but not edited for a certain amount of time are automatically closed by the backend. This command delays this behaviour by increasing the timeout. ================= ========================== Parameter Description ================= ========================== ref UUID / object reference ================= ========================== """ objdsc = self.__get_ref(ref) if not objdsc: raise ValueError(C.make_error("REFERENCE_NOT_FOUND", ref=ref)) if not self.__check_user(ref, user): raise ValueError(C.make_error("NOT_OBJECT_OWNER")) objdsc['last_interaction'] = datetime.datetime.now() with make_session() as session: obj = session.query(OpenObject).filter(OpenObject.ref == ref).one() obj.last_interaction = objdsc['last_interaction'] session.commit() if 'mark_for_deletion' in objdsc: # as this object has been marked for deletion, we have to run the garbage collection # to remove this mark now self.__gc()
def reloadObject(self, user, ref): """ Opens a copy of the object given as ref and closes the original instance. """ item = self.__get_ref(ref) if item is not None: if not self.__check_user(ref, user): raise ValueError(C.make_error("NOT_OBJECT_OWNER")) oid = item['object']['oid'] uuid = item['object']['uuid'] if uuid is None: uuid = item['object']['object'].uuid session_id = item['session_id'] new_item = self.openObject(user, session_id, oid, uuid) # Close original ref and return the new one self.closeObject(user, ref) return new_item else: raise ValueError(C.make_error("REFERENCE_NOT_FOUND", ref=ref))
def retract(self, extension): """ Retracts an extension from the current object """ if not extension in self.__extensions: raise ProxyException(C.make_error('OBJECT_EXTENSION_NOT_ALLOWED', extension=extension)) if self.__extensions[extension] is None: raise ProxyException(C.make_error('OBJECT_NO_SUCH_EXTENSION', extension=extension)) # Collect all extensions that are required due to dependencies.. oTypes = self.__factory.getObjectTypes() for ext in self.__extensions: if self.__extensions[ext]: if extension in oTypes[ext]['requires']: raise ProxyException(C.make_error('OBJECT_EXTENSION_IN_USE', extension=extension, origin=ext)) # Check Acls # Required is the 'd' (delete) right for the extension on the current object. if self.__current_user is not None: topic = "%s.objects.%s" % (self.__env.domain, extension) if not self.__acl_resolver.check(self.__current_user, topic, "d", base=self.__base.dn): self.__log.debug("user '%s' has insufficient permissions to add extension %s to %s, required is %s:%s on %s" % ( self.__current_user, extension, self.__base.dn, topic, "d", self.__base.dn)) raise ACLException(C.make_error('PERMISSION_RETRACT', extension=extension, target=self.__base.dn)) # Unregister the extensions methods for method in list(self.__method_type_map): if self.__method_type_map[method] == extension: del(self.__method_map[method]) del(self.__method_type_map[method]) # Move the extension to retractions self.__retractions[extension] = self.__extensions[extension] self.__extensions[extension] = None
def setUserPassword(self, user, object_dn, password): """ Set a new password for a user """ # Do we have write permissions for the requested attribute env = Environment.getInstance() topic = "%s.objects.%s.attributes.%s" % (env.domain, "User", "userPassword") aclresolver = PluginRegistry.getInstance("ACLResolver") if not aclresolver.check(user, topic, "w", base=object_dn): self.__log.debug( "user '%s' has insufficient permissions to write %s on %s, required is %s:%s" % (user, "isLocked", object_dn, topic, "w")) raise ACLException( C.make_error('PERMISSION_ACCESS', topic, target=object_dn)) user = ObjectProxy(object_dn) method = user.passwordMethod # Try to detect the responsible password method-class pwd_o = self.get_method_by_method_type(method) if not pwd_o: raise PasswordException( C.make_error("PASSWORD_UNKNOWN_HASH", type=method)) # Generate the new password hash using the detected method pwd_str = pwd_o.generate_password_hash(password, method) # Set the password and commit the changes user.userPassword = pwd_str user.commit()
def setTwoFactorMethod(self, user_name, object_dn, factor_method, user_password=None): # Do we have write permissions for the requested attribute self.__check_acl(user_name, object_dn, "w") if factor_method == "None": factor_method = None if factor_method not in self.methods: raise UnknownTwoFAMethod(C.make_error("UNKNOWN_2FA_METHOD", method=factor_method)) # Get the object for the given dn user = ObjectProxy(object_dn) current_method = self.get_method_from_user(user) if current_method == factor_method: # nothing to change return None if current_method is not None: # we need to be verified by user password in order to change the method if user_password is None or not check_auth(user_name, user_password): raise ChangingNotAllowed(C.make_error('CHANGE_2FA_METHOD_FORBIDDEN')) if factor_method == "otp": return self.__enable_otp(user) elif factor_method == "u2f": return self.__enable_u2f(user) elif factor_method is None: # disable two factor auth del self.__settings[user.uuid] self.__save_settings() return None
def registerWebhook(self, user, sender_name, mime_type): topic = "%s.webhook.%s" % (self.env.domain, mime_type) aclresolver = PluginRegistry.getInstance("ACLResolver") if not aclresolver.check(user, topic, "e"): self.log.debug("user '%s' has insufficient permissions to register webhook for mime-type %s" % (user, mime_type)) raise ACLException(C.make_error('PERMISSION_ACCESS', topic)) # check sender_name syntax if not self.name_check.match(sender_name): raise WebhookException(C.make_error('INVALID_WEBHOOK_SENDER_NAME')) # check mime-type syntax if not self.mime_type_check.match(mime_type): raise WebhookException(C.make_error('INVALID_WEBHOOK_MIME_TYPE')) # check for duplicates if mime_type not in self.__handlers: raise WebhookException(C.make_error('NO_REGISTERED_WEBHOOK_HANDLER', mime_type)) path = self.get_path(mime_type, sender_name) if self.settings.has(path): raise WebhookException(C.make_error('EXISTING_WEBHOOK_HANDLER', mime_type, name=sender_name)) self.settings.set(path, str(uuid.uuid4())) return self.getWebhookUrl(), self.settings.get(path)
def setUserPassword(self, user, object_dn, password): """ Set a new password for a user """ # Do we have write permissions for the requested attribute env = Environment.getInstance() topic = "%s.objects.%s.attributes.%s" % (env.domain, "User", "userPassword") aclresolver = PluginRegistry.getInstance("ACLResolver") if not aclresolver.check(user, topic, "w", base=object_dn): self.__log.debug("user '%s' has insufficient permissions to write %s on %s, required is %s:%s" % ( user, "isLocked", object_dn, topic, "w")) raise ACLException(C.make_error('PERMISSION_ACCESS', topic, target=object_dn)) user = ObjectProxy(object_dn) method = user.passwordMethod # Try to detect the responsible password method-class pwd_o = self.get_method_by_method_type(method) if not pwd_o: raise PasswordException(C.make_error("PASSWORD_UNKNOWN_HASH", type=method)) # Generate the new password hash using the detected method pwd_str = pwd_o.generate_password_hash(password, method) # Set the password and commit the changes user.userPassword = pwd_str user.commit()
def setSambaPassword(self, user, object_dn, password): """ Set a new samba-password for a user """ # Do we have read permissions for the requested attribute env = Environment.getInstance() topic = "%s.objects.%s.attributes.%s" % (env.domain, "User", "sambaNTPassword") aclresolver = PluginRegistry.getInstance("ACLResolver") if not aclresolver.check(user, topic, "w", base=object_dn): self.__log.debug("user '%s' has insufficient permissions to write %s on %s, required is %s:%s" % ( user, "isLocked", object_dn, topic, "w")) raise ACLException(C.make_error('PERMISSION_ACCESS', topic, target=object_dn)) topic = "%s.objects.%s.attributes.%s" % (env.domain, "User", "sambaLMPassword") aclresolver = PluginRegistry.getInstance("ACLResolver") if not aclresolver.check(user, topic, "w", base=object_dn): self.__log.debug("user '%s' has insufficient permissions to write %s on %s, required is %s:%s" % ( user, "isLocked", object_dn, topic, "w")) raise ACLException(C.make_error('PERMISSION_ACCESS', topic, target=object_dn)) # Set the password and commit the changes user = ObjectProxy(object_dn) user.sambaNTPassword = nthash.encrypt(password) user.sambaLMPassword = lmhash.encrypt(password) user.commit()
def _execute_embedded_script(self, script): log = logging.getLogger("%s.%s" % (__name__, self.uuid)) try: log.info("start executing workflow script") env = dict(data=self._get_data()) dispatcher = PluginRegistry.getInstance('CommandRegistry') def make_dispatch(method): def call(*args, **kwargs): return dispatcher.dispatch(self.__user, self.__session_id, method, *args, **kwargs) return call # Add public calls for method in dispatcher.getMethods(): env[method] = make_dispatch(method) # add logger env['log'] = log exec(script, env) log.info("finished executing workflow script") if self.__user is not None: # tell the frontend e = EventMaker() ev = e.Event( e.BackendDone(e.UUID(self.uuid), e.Type("workflow"), e.State("success"))) event_object = objectify.fromstring( etree.tostring(ev, pretty_print=True).decode('utf-8')) SseHandler.notify(event_object, channel="user.%s" % self.__user) except Exception as ex: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] log.error("Exception while executing the embedded script:") log.error("%s line %s" % (fname, exc_tb.tb_lineno)) log.error(exc_type) log.error(exc_obj) if GosaErrorHandler.get_error_id(str(ex)) is None: ex = ScriptError(C.make_error('WORKFLOW_SCRIPT_ERROR', str(ex))) e = EventMaker() ev = e.Event( e.BackendDone(e.UUID(self.uuid), e.Type("workflow"), e.State("error"), e.Message(str(ex)))) event_object = objectify.fromstring( etree.tostring(ev, pretty_print=True).decode('utf-8')) SseHandler.notify(event_object, channel="user.%s" % self.__user) raise ex return True
def __check_res(self, uuid, res): if not res: raise EntryNotFound(C.make_error("ENTRY_UUID_NOT_FOUND", uuid=uuid)) if len(res) != 1: raise EntryNotFound( C.make_error("ENTRY_UUID_NOT_UNIQUE", uuid=uuid))
def dispatch(self, user, session_id, func, *arg, **larg): """ The dispatch method will try to call the specified function and checks for user. Handlers like JSONRPC should use this function to dispatch the real calls. ========== ============ Parameter Description ========== ============ user the calling users name session_id the calling session id func method to call args ordinary argument list/dict ========== ============ ``Return:`` the real methods result """ # Check for user authentication (if user is 'self' this is an internal call) if not user and user != self: raise CommandNotAuthorized(C.make_error("COMMAND_NO_USERNAME", method=func)) # Check if the command is available if not func in self.commands: raise CommandInvalid(C.make_error("COMMAND_NOT_DEFINED", method=func)) # Check for permission (if user equals 'self' then this is an internal call) if user != self: chk_options = dict(zip(self.commands[func]['sig'], arg)) chk_options.update(larg) acl = PluginRegistry.getInstance("ACLResolver") if not acl.check(user, "%s.%s.%s" % (self.env.domain, "command", func), "x", options=chk_options): raise CommandNotAuthorized(C.make_error("PERMISSION_EXEC", method=func)) # Convert to list arg = list(arg) # Check if call is interested in calling user ID, prepend it if self.callNeedsUser(func): if user != self: arg.insert(0, user) else: arg.insert(0, None) # Check if call is interested in calling session ID, prepend it if self.callNeedsSession(func): index = 1 if self.callNeedsUser(func) else 0 if user != self: arg.insert(index, session_id) else: arg.insert(index, None) # Handle function type (additive, first match, regular) (clazz, method) = self.path2method(self.commands[func]['path']) return PluginRegistry.modules[clazz].\ __getattribute__(method)(*arg, **larg)
def extend(self, extension): """ Extends the base-object with the given extension """ # Is this a valid extension? if not extension in self.__extensions: raise ProxyException(C.make_error('OBJECT_EXTENSION_NOT_ALLOWED', extension=extension)) # Is this extension already active? # if self.__extensions[extension] is not None: # raise ProxyException(C.make_error('OBJECT_EXTENSION_DEFINED', extension=extension)) # Ensure that all precondition for this extension are fulfilled object_types = self.__factory.getObjectTypes() for required_extension in object_types[extension]['requires']: if not required_extension in self.__extensions or self.__extensions[required_extension] is None: raise ProxyException(C.make_error('OBJECT_EXTENSION_DEPENDS', extension=extension, missing=required_extension)) # Check Acls # Required is the 'c' (create) right for the extension on the current object. if self.__current_user is not None: topic = "%s.objects.%s" % (self.__env.domain, extension) if not self.__acl_resolver.check(self.__current_user, topic, "c", base=self.__base.dn): self.__log.debug("user '%s' has insufficient permissions to add extension %s to %s, required is %s:%s on %s" % ( self.__current_user, extension, self.__base.dn, topic, "c", self.__base.dn)) raise ACLException(C.make_error('PERMISSION_EXTEND', extension=extension, target=self.__base.dn)) # Create extension if extension in self.__retractions: self.__extensions[extension] = self.__retractions[extension] del self.__retractions[extension] else: mode = "extend" current_object = ObjectProxy(self.dn) if current_object.__extensions[extension]: mode = "update" self.__extensions[extension] = self.__factory.getObject(extension, self.__base.uuid, mode=mode) self.__extensions[extension].parent = self self.__extensions[extension]._owner = self.__current_user # Register the extensions methods object_types = self.__factory.getObjectTypes() for method in object_types[extension]['methods']: self.__method_map[method] = getattr(self.__extensions[extension], method) self.__method_type_map[method] = extension # Set initial values for foreign properties self.populate_to_foreign_properties(extension)
def get_final_dn(self, base_dn, data, backend_params): # Check if obligatory information for assembling the DN are # provided if not 'RDN' in backend_params: raise RDNNotSpecified(C.make_error("RDN_NOT_SPECIFIED")) # Build unique DN using maybe optional RDN parameters rdns = [d.strip() for d in backend_params['RDN'].split(",")] FixedRDN = backend_params['FixedRDN'] if 'FixedRDN' in backend_params else None dn = self.get_uniq_dn(rdns, base_dn, data, FixedRDN) if not dn: raise DNGeneratorError(C.make_error("NO_UNIQUE_DN", base=base_dn, rdns=", ".join(rdns))) return dn
def process(self, obj, key, valDict, method, number, domain, group_type=0): if number == "None": raise SambaException( C.make_error("ATTRIBUTE_NOT_FOUND", "uidNumber|gidNumber")) if domain == "None": raise SambaException( C.make_error("ATTRIBUTE_NOT_FOUND", "sambaDomainName")) index = PluginRegistry.getInstance("ObjectIndex") sid = index.search({ '_type': 'SambaDomain', 'sambaDomainName': domain }, { 'sambaSID': 1, 'sambaAlgorithmicRidBase': 1 }) if len(sid) != 1: raise SambaException( C.make_error("SAMBA_DOMAIN_WITHOUT_SID", domain)) dsid = sid[0]['sambaSID'][0] if 'sambaAlgorithmicRidBase' in sid[0]: ridbase = int(sid[0]['sambaAlgorithmicRidBase'][0]) else: ridbase = int(self.env.config.get('samba.ridbase', default=1000)) # Generate a sid for groups or users. group_type = int(group_type) number = int(number) if "group" == method: if group_type == 0: sid = dsid + "-" + str(number * 2 + ridbase + 1) else: sid = dsid + "-" + str(group_type) valDict[key]['value'] = [sid] elif "user" == method: sid = dsid + "-" + str(number * 2 + ridbase) valDict[key]['value'] = [sid] else: raise SambaException(C.make_error("SAMBA_NO_SID_TYPE", type=method)) return key, valDict
def create(self, base, data, params, foreign_keys=None, needed=None, user=None): """ Creates a new database entry """ # All entries require a naming attribute, if it's not available we cannot generate a dn for the entry if not 'rdn' in params: raise RDNNotSpecified(C.make_error("RDN_NOT_SPECIFIED")) # Split given rdn-attributes into a list. rdns = [d.strip() for d in params['rdn'].split(",")] # Get FixedRDN attribute FixedRDN = params['FixedRDN'] if 'FixedRDN' in params else None # Get a unique dn for this entry, if there was no free dn left (None) throw an error object_dn = self.get_uniq_dn(rdns, base, data, FixedRDN) if not object_dn: raise DNGeneratorError( C.make_error("NO_UNIQUE_DN", base=base, rdns=", ".join(rdns))) # Build the entry that will be written to the json-database json = self.__load() str_uuid = str(uuid.uuid1()) obj = { 'dn': object_dn, 'type': params['type'], 'parentDN': base, 'modifyTimestamp': datetime.datetime.now().isoformat(), 'createTimestamp': datetime.datetime.now().isoformat() } for attr in data: obj[attr] = data[attr]['value'] # Append the entry to the databse and save the changes if not str_uuid in json: json[str_uuid] = {} json[str_uuid][params['type']] = obj self.__save(json) # Return the uuid of the generated entry return str_uuid
def getGuiDialogs(self, objectType): factory = ObjectFactory.getInstance() if objectType not in factory.getObjectTypes(): raise GOsaException( C.make_error("OBJECT_UNKNOWN_TYPE", type=objectType)) return factory.getObjectDialogs(objectType)
def serve(self): """ Start serving the command registry to the outside world. Send hello and register event callbacks. """ for clazz in PluginRegistry.modules.values(): for mname, method in getmembers(clazz): if ismethod(method) and hasattr(method, "isCommand"): func = mname # Adjust documentation if not method.__help__: raise CommandInvalid(C.make_error("COMMAND_WITHOUT_DOCS", method=func)) doc = re.sub("(\s|\n)+", " ", method.__help__).strip() self.log.debug("registering %s" % func) info = { 'name': func, 'path': "%s.%s" % (clazz.__class__.__name__, mname), 'sig': [] if not getargspec(method).args else getargspec(method).args, 'target': clazz.get_target(), 'type': getattr(method, "type", NORMAL), 'doc': doc, } if 'self' in info['sig']: info['sig'].remove('self') self.commands[func] = info
def accountUnlockable(self, user, object_dn): index = PluginRegistry.getInstance("ObjectIndex") # Do we have read permissions for the requested attribute env = Environment.getInstance() topic = "%s.objects.%s.attributes.%s" % (env.domain, "User", "isLocked") aclresolver = PluginRegistry.getInstance("ACLResolver") if not aclresolver.check(user, topic, "r", base=object_dn): self.__log.debug("user '%s' has insufficient permissions to read %s on %s, required is %s:%s" % ( user, "isLocked", object_dn, topic, "r")) raise ACLException(C.make_error('PERMISSION_ACCESS', topic, target=object_dn)) res = index.search({'dn': object_dn, 'userPassword': '******'}, {'userPassword': 1}) if len(res): hsh = res[0]['userPassword'][0] else: # No password hash -> cannot lock/unlock account return False # Try to detect the responsible password method-class pwd_o = self.detect_method_by_hash(hsh) if not pwd_o: # Could not identify password method return False return pwd_o.isUnlockable(hsh)
def get_filter(name): for entry in pkg_resources.iter_entry_points("gosa.object.filter"): module = entry.load() if module.__name__ == name: return module raise KeyError(C.make_error("FILTER_NO_INSTANCE", filter=name))
def process(self, obj, key, valDict): if len(valDict[key]['value']) and type(valDict[key]['value'][0]) == str: valDict[key]['value'][0] = valDict[key]['value'][0].rstrip("$") else: raise ValueError(C.make_error("TYPE_UNKNOWN", self.__class__.__name__, type=type(valDict[key]['value']))) return key, valDict
def process(self, topic, message): try: req = loads(message) except ValueError as e: raise ValueError(C.make_error("INVALID_JSON", data=str(e))) try: id_ = req['id'] name = req['method'] args = req['params'] kwargs = req['kwparams'] if 'user' in req: user = req['user'] else: user = topic.split("/")[2] sid = req['session_id'] if 'session_id' in req else None except KeyError as e: self.log.error("KeyError: %s" % e) raise BadServiceRequest(message) self.log.debug("received call [%s, user=%s, session-id=%s] for %s: %s(%s,%s)" % (id_, user, sid, topic, name, args, kwargs)) try: return id_, self.__command_registry.dispatch(user, sid, name, *args, **kwargs) except Exception as e: # Write exception to log exc_type, exc_value, exc_traceback = sys.exc_info() self.log.error("".join(traceback.format_exception(exc_type, exc_value, exc_traceback))) raise e
def insert(self, obj, skip_base_check=False): if not skip_base_check: pdn = self.__session.query(ObjectInfoIndex.dn).filter( ObjectInfoIndex.dn == obj.get_parent_dn()).one_or_none() # No parent? if not pdn: self.log.debug( "ignoring object that has no base in the current index: " + obj.dn) return parent = self._get_object(obj.get_parent_dn()) if not parent.can_host(obj.get_base_type()): self.log.debug( "ignoring object that is not relevant for the index: " + obj.dn) return self.log.debug("creating object index for %s" % obj.uuid) uuid = self.__session.query(ObjectInfoIndex.uuid).filter( ObjectInfoIndex.uuid == obj.uuid).one_or_none() if uuid: raise IndexException( C.make_error('OBJECT_EXISTS', "base", uuid=obj.uuid)) self.__save(obj.asJSON(True))
def process(self, topic, message): try: req = loads(message) except ValueError as e: raise ValueError(C.make_error("INVALID_JSON", data=str(e))) try: id_ = req['id'] name = req['method'] args = req['params'] user = req['user'] if 'user' in req else topic.split("/")[2] sid = req['session_id'] if 'session_id' in req else None except KeyError as e: self.log.error("KeyError: %s" % e) raise BadServiceRequest(message) self.log.debug("received call [%s] for %s: %s(%s)" % (id_, topic, name, args)) try: return id_, self.__command_registry.dispatch( user, sid, name, *args) except Exception as e: # Write exception to log exc_type, exc_value, exc_traceback = sys.exc_info() self.log.error("".join( traceback.format_exception(exc_type, exc_value, exc_traceback))) raise e
def accountUnlockable(self, user, object_dn): index = PluginRegistry.getInstance("ObjectIndex") # Do we have read permissions for the requested attribute env = Environment.getInstance() topic = "%s.objects.%s.attributes.%s" % (env.domain, "User", "isLocked") aclresolver = PluginRegistry.getInstance("ACLResolver") if not aclresolver.check(user, topic, "r", base=object_dn): self.__log.debug( "user '%s' has insufficient permissions to read %s on %s, required is %s:%s" % (user, "isLocked", object_dn, topic, "r")) raise ACLException( C.make_error('PERMISSION_ACCESS', topic, target=object_dn)) res = index.search({ 'dn': object_dn, 'userPassword': '******' }, {'userPassword': 1}) if len(res): hsh = res[0]['userPassword'][0] else: # No password hash -> cannot lock/unlock account return False # Try to detect the responsible password method-class pwd_o = self.detect_method_by_hash(hsh) if not pwd_o: # Could not identify password method return False return pwd_o.isUnlockable(hsh)
def searchForObjectDetails(self, user, extension, attribute, search_filter, attributes, skip_values, options=None): """ Search selectable items valid for the attribute "extension.attribute". This is used to add new groups to the users groupMembership attribute. """ # Extract the the required information about the object # relation out of the BackendParameters for the given extension. object_factory = ObjectFactory.getInstance() be_data = object_factory.getObjectBackendParameters( extension, attribute) if not be_data: raise GOsaException( C.make_error("BACKEND_PARAMETER_MISSING", extension=extension, attribute=attribute)) # Collection basic information object_type, object_attribute, _, _ = be_data[attribute] return self.searchObjects(user, object_type, object_attribute, search_filter, attributes, skip_values, options)
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 process(self, obj, key, valDict): # Create a list with all relevant attributes. alist = ['inVacation', 'activateSpamFilter', 'mailSizeFilter', 'localDelivery', 'skipOwnMailbox', 'customSieveScript'] # Build up a list of values to encode. res = {} for entry in alist: if not len(valDict[entry]['value']): raise AttributeError(C.make_error('ATTRIBUTE_MANDATORY', entry)) else: res[entry] = valDict[entry]['value'][0] # Encode the mail delivery mode attribute. result = "" if res['inVacation']: result += "V" if res['activateSpamFilter']: result += "S" if res['mailSizeFilter']: result += "R" if res['localDelivery']: result += "L" if res['skipOwnMailbox']: result += "I" if res['customSieveScript']: result += "C" valDict[key]['value'] = ["[" + result + "]"] return key, valDict
def getUserDetails(self, userid): index = PluginRegistry.getInstance("ObjectIndex") res = index.search({ '_type': 'User', 'uid': userid }, { 'sn': 1, 'givenName': 1, 'cn': 1, 'dn': 1, '_uuid': 1, '_last_changed': 1 }) if len(res) == 0: raise GOsaException(C.make_error("UNKNOWN_USER", target=userid)) cache_path = self.env.config.get('user.image-path', default="/var/lib/gosa/images") icon = "@Ligature/user" if os.path.exists( os.path.join(cache_path, res[0]['_uuid'], "jpegPhoto", "0", "64.jpg")): icon = "/images/%s/jpegPhoto/0/64.jpg?c=%s" % ( res[0]['_uuid'], res[0]["_last_changed"]) return ({ 'sn': res[0]['sn'][0], 'givenName': res[0]['givenName'][0], 'dn': res[0]['dn'], 'uuid': res[0]['_uuid'], 'icon': icon, 'cn': res[0]['cn'][0] })
def process(self, obj, key, valDict): # Create a dictionary with all relevant samba attributes. alist = [ 'CtxCallback', 'CtxCallbackNumber', 'CtxCfgFlags1', 'CtxCfgPresent', 'CtxInitialProgram', 'CtxKeyboardLayout', 'CtxMaxConnectionTime', 'CtxMaxDisconnectionTime', 'CtxMaxIdleTime', 'Ctx_flag_connectClientDrives', 'CtxMinEncryptionLevel', 'oldStorageBehavior', 'CtxNWLogonServer', 'CtxShadow', 'CtxWFHomeDir', 'CtxWFHomeDirDrive', 'CtxWFProfilePath', 'CtxWorkDirectory', 'Ctx_flag_brokenConn', 'Ctx_flag_connectClientPrinters', 'Ctx_flag_defaultPrinter', 'Ctx_flag_inheritMode', 'Ctx_flag_reConn', 'Ctx_shadow', 'Ctx_flag_tsLogin' ] # Build up a list of values to encode. res = {} for entry in alist: if not len(valDict[entry]['value']): raise AttributeError(C.make_error('ATTRIBUTE_MANDATORY', entry)) else: res[entry] = valDict[entry]['value'][0] # Encode the sambaMungedDial attribute. result = SambaMungedDial.encode(res) valDict[key]['value'] = [result] return key, valDict
def process(self, obj, key, valDict): # Create a dictionary with all relevant samba attributes. alist = ['CtxCallback', 'CtxCallbackNumber', 'CtxCfgFlags1', 'CtxCfgPresent', 'CtxInitialProgram', 'CtxKeyboardLayout', 'CtxMaxConnectionTime', 'CtxMaxDisconnectionTime', 'CtxMaxIdleTime', 'Ctx_flag_connectClientDrives', 'CtxMinEncryptionLevel', 'oldStorageBehavior', 'CtxNWLogonServer', 'CtxShadow', 'CtxWFHomeDir', 'CtxWFHomeDirDrive', 'CtxWFProfilePath', 'CtxWorkDirectory', 'Ctx_flag_brokenConn', 'Ctx_flag_connectClientPrinters', 'Ctx_flag_defaultPrinter', 'Ctx_flag_inheritMode', 'Ctx_flag_reConn', 'Ctx_shadow', 'Ctx_flag_tsLogin'] # Build up a list of values to encode. res = {} for entry in alist: if not len(valDict[entry]['value']): raise AttributeError(C.make_error('ATTRIBUTE_MANDATORY', entry)) else: res[entry] = valDict[entry]['value'][0] # Encode the sambaMungedDial attribute. result = SambaMungedDial.encode(res) valDict[key]['value'] = [result] return key, valDict
def asJSON(self, only_indexed=False): """ Returns JSON representations for the base-object and all its extensions. """ #TODO: only_indexed!? atypes = self.__factory.getAttributeTypes() # Check permissions topic = "%s.objects.%s" % (self.__env.domain, self.__base_type) if self.__current_user is not None and not self.__acl_resolver.check(self.__current_user, topic, "r", base=self.dn): self.__log.debug("user '%s' has insufficient permissions for asJSON on %s, required is %s:%s" % ( self.__current_user, self.dn, topic, "r")) raise ACLException(C.make_error('PERMISSION_ACCESS', topic, target=self.dn)) res = {'dn': self.__base.dn, '_type': self.__base.__class__.__name__, '_parent_dn': self.get_parent_dn(self.__base.dn), '_adjusted_parent_dn': self.get_adjusted_parent_dn(self.__base.dn), '_uuid': self.__base.uuid} # Create non object pseudo attributes if self.__base.modifyTimestamp: res['_last_changed'] = time.mktime(self.__base.modifyTimestamp.timetuple()) res['_extensions'] = [k for k in self.__extensions.keys() if self.__extensions[k]] props = self.__property_map for propname in self.__property_map: # Use the object-type conversion method to get valid item string-representations. prop_value = props[propname]['value'] if props[propname]['type'] != "Binary": res[propname] = atypes[props[propname]['type']].convert_to("UnicodeString", prop_value) return res
def is_responsible_for_password_hash(self, password_hash): """ Checks whether this class is responsible for this kind of password hashes or not. """ raise NotImplementedError( C.make_error('NOT_IMPLEMENTED', method="is_responsible_for_password_hash"))
def build_dn_list(self, rdns, base, data, FixedRDN): """ Build a list of possible DNs for the given properties """ fix = rdns[0] var = rdns[1:] if len(rdns) > 1 else [] dns = [fix] # Check if we've have to use a fixed RDN. if FixedRDN: return["%s,%s" % (FixedRDN, base)] # Bail out if fix part is not in data if not fix in data: raise DNGeneratorError(C.make_error("GENERATOR_RDN_ATTRIBUTE_MISSING", fix)) # Append possible variations of RDN attributes if var: for rdn in permutations(var + [None] * (len(var) - 1), len(var)): dns.append("%s,%s" % (fix, ",".join(filter(lambda x: x and x in data and data[x], list(rdn))))) dns = list(set(dns)) # Assemble DN of RDN combinations dn_list = [] for t in [tuple(d.split(",")) for d in dns]: ndn = [] for k in t: ndn.append("%s=%s" % (k, ldap.dn.escape_dn_chars(data[k]['value'][0]))) dn_list.append("+".join(ndn) + "," + base) return sorted(dn_list, key=len)
def move(self, item_uuid, new_base, needed=None, user=None): """ Moves an entry to another base """ json = self.__load() if item_uuid in json: for obj in json[item_uuid]: if "dn" in json[item_uuid][obj]: # Update the source entry entry = json[item_uuid][obj] entry['dn'] = re.sub( re.escape(entry['parentDN']) + "$", new_base, entry['dn']) entry['parentDN'] = new_base # Check if we can move the entry if self.exists(entry['dn']): raise BackendError( C.make_error("TARGET_EXISTS", target=entry['dn'])) # Save the changes json[item_uuid][obj] = entry self.__save(json) return True return False
def getUserPPDs(self, user): index = PluginRegistry.getInstance("ObjectIndex") res = index.search({"_type": "User", "uid": user}, {"dn": 1}) if len(res) == 0: raise EntryNotFound(C.make_error("USER_NOT_FOUND", topic=user)) object = ObjectProxy(res[0]["dn"]) printer_cns = [] if object.is_extended_by("GotoEnvironment"): printer_cns.append(object.gotoPrinters) if object.is_extended_by("PosixUser"): for group_cn in object.groupMembership: group = ObjectProxy(group_cn) if group.is_extended_by("GotoEnvironment"): printer_cns.append(group.gotoPrinters) # collect all PPDs res = index.search({ "_type": "GotoPrinter", "cn": { "in_": printer_cns } }, {"gotoPrinterPPD": 1}) ppds = [] for r in res: ppds.append(r["gotoPrinterPPD"]) return ppds
def build_dn_list(self, rdns, base, data, FixedRDN): fix = rdns[0] var = rdns[1:] if len(rdns) > 1 else [] dns = [fix] # Check if we've have to use a fixed RDN. if FixedRDN: return["%s,%s" % (FixedRDN, base)] # Bail out if fix part is not in data if not fix in data: raise DNGeneratorError(C.make_error("ATTRIBUTE_NOT_FOUND", attribute=fix)) # Append possible variations of RDN attributes if var: for rdn in permutations(var + [None] * (len(var) - 1), len(var)): dns.append("%s,%s" % (fix, ",".join(filter(lambda x: x and x in data and data[x], list(rdn))))) dns = list(set(dns)) # Assemble DN of RDN combinations dn_list = [] for t in [tuple(d.split(",")) for d in dns]: ndn = [] for k in t: ndn.append("%s=%s" % (k, ldap.dn.escape_dn_chars(data[k]['value'][0]))) dn_list.append("+".join(ndn) + "," + base) return sorted(dn_list, key=len)
def process(self, obj, key, valDict): # Create a list with all relevant attributes. alist = [ 'inVacation', 'activateSpamFilter', 'mailSizeFilter', 'localDelivery', 'skipOwnMailbox', 'customSieveScript' ] # Build up a list of values to encode. res = {} for entry in alist: if not len(valDict[entry]['value']): raise AttributeError(C.make_error('ATTRIBUTE_MANDATORY', entry)) else: res[entry] = valDict[entry]['value'][0] # Encode the mail delivery mode attribute. result = "" if res['inVacation']: result += "V" if res['activateSpamFilter']: result += "S" if res['mailSizeFilter']: result += "R" if res['localDelivery']: result += "L" if res['skipOwnMailbox']: result += "I" if res['customSieveScript']: result += "C" valDict[key]['value'] = ["[" + result + "]"] return key, valDict
def removeObject(self, user, oid, *args, **kwargs): """ Open object on the agent side and calls its remove method ================= ========================== Parameter Description ================= ========================== oid OID of the object to create args/kwargs Arguments to be used when getting an object instance ================= ========================== ``Return``: True """ # In case of "object" we want to check the lock if oid == 'object': lck = self.__get_lock(args[0]) if lck: raise Exception( C.make_error( "OBJECT_LOCKED", object=args[0], user=lck['user'], when=lck['created'].strftime("%Y-%m-%d (%H:%M:%S)"))) # Use oid to find the object type obj_type = self.__get_object_type(oid) # Make object instance and store it kwargs['user'] = user obj = obj_type(*args, **kwargs) obj.remove() return True
def get_operator(name): for entry in pkg_resources.iter_entry_points("gosa.object.operator"): module = entry.load() if module.__name__ == name: return module raise KeyError(C.make_error("OPERATOR_NO_INSTANCE", operator=name))
def removeObject(self, user, oid, *args, **kwargs): """ Open object on the agent side and calls its remove method ================= ========================== Parameter Description ================= ========================== oid OID of the object to create args/kwargs Arguments to be used when getting an object instance ================= ========================== ``Return``: True """ # In case of "object" we want to check the lock if oid == 'object': lck = self.__get_lock(args[0]) if lck: raise Exception(C.make_error("OBJECT_LOCKED", object=args[0], user=lck['user'], when=lck['created'].strftime("%Y-%m-%d (%H:%M:%S)") )) # Use oid to find the object type obj_type = self.__get_object_type(oid) # Make object instance and store it kwargs['user'] = user obj = obj_type(*args, **kwargs) obj.remove() return True
def remove(self, recursive=False): """ Removes the currently proxied object. """ # Check ACLs # We need the 'd' right for the current base-object and all its active extensions to be able to remove it. if self.__current_user is not None: required_acl_objects = [self.__base_type] + [ext for ext, item in self.__extensions.items() if item is not None] for ext_type in required_acl_objects: topic = "%s.objects.%s" % (self.__env.domain, ext_type) if not self.__acl_resolver.check(self.__current_user, topic, "d", base=self.dn): self.__log.debug("user '%s' has insufficient permissions to remove %s, required is %s:%s" % ( self.__current_user, self.__base.dn, topic, 'd')) raise ACLException(C.make_error('PERMISSION_REMOVE', target=self.__base.dn)) zope.event.notify(ObjectChanged("pre object remove", self.__base)) if recursive: # Load all children and remove them, starting from the most # nested ones. index = PluginRegistry.getInstance("ObjectIndex") children = index.search({"dn": ["%," + self.__base.dn]}, {'dn': 1}) children = [c['dn'] for c in children] children.sort(key=len, reverse=True) for child in children: c_obj = ObjectProxy(child) c_obj.remove(recursive=True) else: # Test if we've children index = PluginRegistry.getInstance("ObjectIndex") if len(index.search({"dn": "%," + self.__base.dn}, {'dn': 1})): raise ProxyException(C.make_error('OBJECT_HAS_CHILDREN', target=self.__base.dn)) for extension in [e for e in self.__extensions.values() if e]: extension.remove_refs() extension.retract() self.__base.remove_refs() self.__base.remove() zope.event.notify(ObjectChanged("post object remove", self.__base))
def get_connection(self): """ Get a new connection from the pool. ``Return``: LDAP connection """ # Are there free connections in the pool? try: next_free = LDAPHandler.connection_usage.index(False) except ValueError: raise LDAPException(C.make_error("LDAP_NO_CONNECTIONS")) # Need to initialize? if not LDAPHandler.connection_handle[next_free]: get = self.env.config.get self.log.debug("initializing LDAP connection to %s" % str(self.__url)) conn = ldap.ldapobject.ReconnectLDAPObject( "%s://%s" % (self.__url.urlscheme, self.__url.hostport), retry_max=int(get("ldap.retry-max", default=3)), retry_delay=int(get("ldap.retry-delay", default=5))) # We only want v3 conn.protocol_version = ldap.VERSION3 # If no SSL scheme used, try TLS if get("ldap.tls", default="True").lower( ) == "true" and ldap.TLS_AVAIL and self.__url.urlscheme != "ldaps": try: conn.start_tls_s() except ldap.PROTOCOL_ERROR as detail: self.log.debug( "cannot use TLS, falling back to unencrypted session") try: # Simple bind? if self.__bind_dn: self.log.debug("starting simple bind using '%s'" % self.__bind_dn) conn.simple_bind_s(self.__bind_dn, self.__bind_secret) elif self.__bind_user: self.log.debug("starting SASL bind using '%s'" % self.__bind_user) auth_tokens = ldap.sasl.digest_md5(self.__bind_user, self.__bind_secret) conn.sasl_interactive_bind_s("", auth_tokens) else: self.log.debug("starting anonymous bind") conn.simple_bind_s() except ldap.INVALID_CREDENTIALS as detail: self.log.error("LDAP authentication failed: %s" % str(detail)) LDAPHandler.connection_handle[next_free] = conn # Lock entry LDAPHandler.connection_usage[next_free] = True return LDAPHandler.connection_handle[next_free]
def diffObject(self, user, ref): """ Opens a copy of the object given as ref and returns a diff - if any. """ if not ref in self.__stack: return None if not self.__check_user(ref, user): raise ValueError(C.make_error("NOT_OBJECT_OWNER")) # Load current object item = self.__stack[ref] current_obj = ObjectProxy(item['object']['dn']) # Load cache object cache_obj = item['object']['object'] ## ## Generate delta ## delta = {'attributes': {'added': {}, 'removed': [], 'changed': {}, 'blocked_by': {}}, 'extensions': {'added': [], 'removed': []}} # Compare extension list crnt_extensions = set(current_obj.get_object_info()['extensions'].items()) cche_extensions = set(cache_obj.get_object_info()['extensions'].items()) for _e, _s in crnt_extensions - cche_extensions: if _s: delta['extensions']['added'].append(_e) else: delta['extensions']['removed'].append(_e) # Compare attribute contents crnt_attributes = dict(filter(lambda x: x[1] is not None, current_obj.get_attribute_values()['value'].items())) cche_attributes = dict(filter(lambda x: x[1] is not None, cache_obj.get_attribute_values()['value'].items())) all_attributes = [] for _k, _v in crnt_attributes.items(): if _k in cche_attributes: if _v != cche_attributes[_k]: delta['attributes']['changed'][_k] = _v all_attributes.append(_k) else: delta['attributes']['added'][_k] = _v all_attributes.append(_k) for _k, _v in cche_attributes.items(): # Don't add the individual attributes of extensions that are removed anyway if current_obj.get_extension_off_attribute(_k) in delta['extensions']['removed']: continue if not _k in crnt_attributes: delta['attributes']['removed'].append(_k) all_attributes.append(_k) # Find blocking dependencies between attributes details = current_obj.get_attributes(detail=True) for attribute_name in all_attributes: delta['attributes']['blocked_by'][attribute_name] = list(map(lambda x: x['name'], details[attribute_name]['blocked_by'])) return delta
def process(self, obj, key, valDict): if len(valDict[key]['value']) and type(valDict[key]['value'][0]) == str: valDict['sambaNTPassword']['value'] = [nthash.encrypt(valDict[key]['value'][0])] valDict['sambaLMPassword']['value'] = [lmhash.encrypt(valDict[key]['value'][0])] else: raise ValueError(C.make_error("TYPE_UNKNOWN", self.__class__.__name__, type=type(valDict[key]['value']))) return key, valDict
def __call_needs(self, func, name): if not func in self.commands: raise CommandInvalid(C.make_error("COMMAND_NOT_DEFINED", method=func)) (clazz, method) = self.path2method(self.commands[func]['path']) method = PluginRegistry.modules[clazz].__getattribute__(method) return getattr(method, name, False)
def __getattr__(self, name): # Valid method? and enough permissions? if name in self.__method_map: # Check permissions # To execute a method the 'x' permission is required. attr_type = self.__method_type_map[name] topic = "%s.objects.%s.methods.%s" % (self.__env.domain, attr_type, name) if self.__current_user is not None and not self.__acl_resolver.check(self.__current_user, topic, "x", base=self.dn): self.__log.debug("user '%s' has insufficient permissions to execute %s on %s, required is %s:%s" % ( self.__current_user, name, self.dn, topic, "x")) raise ACLException(C.make_error('PERMISSION_ACCESS', topic, target=self.dn)) return self.__method_map[name] if name == 'modifyTimestamp': timestamp = self.__base.modifyTimestamp for obj in self.__extensions.values(): if obj and obj.modifyTimestamp and timestamp < obj.modifyTimestamp: timestamp = obj.modifyTimestamp return timestamp # Valid attribute? if not name in self.__attribute_map: raise AttributeError(C.make_error('ATTRIBUTE_NOT_FOUND', name)) # Do we have read permissions for the requested attribute attr_type = self.__attribute_type_map[name] topic = "%s.objects.%s.attributes.%s" % (self.__env.domain, attr_type, name) if self.__current_user is not None and not self.__acl_resolver.check(self.__current_user, topic, "r", base=self.dn): self.__log.debug("user '%s' has insufficient permissions to read %s on %s, required is %s:%s" % ( self.__current_user, name, self.dn, topic, "r")) raise ACLException(C.make_error('PERMISSION_ACCESS', topic, target=self.dn)) # Load from primary object base_object = self.__attribute_map[name]['base'] if self.__base_type == base_object: return getattr(self.__base, name) # Check for extensions if base_object in self.__extensions and self.__extensions[base_object]: return getattr(self.__extensions[base_object], name) # Not set return None
def registerWebhook(self, user, sender_name, content_type): topic = "%s.webhook.%s" % (self.env.domain, content_type) aclresolver = PluginRegistry.getInstance("ACLResolver") if not aclresolver.check(user, topic, "e"): self.__log.debug("user '%s' has insufficient permissions to register webhook for content type %s" % (user, content_type)) raise ACLException(C.make_error('PERMISSION_ACCESS', topic)) if content_type not in self.__handlers: raise WebhookException(C.make_error('NO_REGISTERED_WEBHOOK_HANDLER', content_type)) if content_type not in self.__hooks: self.__hooks[content_type] = {} if sender_name not in self.__hooks[content_type]: self.__hooks[content_type] = bytes(uuid.uuid4(), 'ascii') return self.get_webhook_url(), self.__hooks[content_type][sender_name]