From e43083a56dfc6d43045a553732e0b4c871b9a40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Mon, 13 Jul 2015 17:50:38 +0200 Subject: [PATCH 01/36] [fix] Display YunoHost packages versions (fix #11) --- bin/yunohost-api | 6 +++++- data/actionsmap/yunohost.yml | 8 +++++--- lib/yunohost/__init__.py | 38 ++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/bin/yunohost-api b/bin/yunohost-api index a15ba4f34..84f38c661 100755 --- a/bin/yunohost-api +++ b/bin/yunohost-api @@ -155,10 +155,14 @@ if __name__ == '__main__': _init_moulinette() from moulinette import (api, MoulinetteError) + from yunohost import get_versions try: # Run the server api(_retrieve_namespaces(), port=6787, - routes={('GET', '/installed'): is_installed}, + routes={ + ('GET', '/installed'): is_installed, + ('GET', '/version'): get_versions, + }, use_cache=USE_CACHE, use_websocket=USE_WEBSOCKET) except MoulinetteError as e: _die(e.strerror, m18n.g('error')) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index d05ffeb5c..7f3ae9483 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -54,9 +54,11 @@ _global: arguments: -v: full: --version - help: Display moulinette version - action: version - version: moulinette %version% + help: Display YunoHost packages versions + action: callback + callback: + method: yunohost.get_versions + return: true ############################# # User # diff --git a/lib/yunohost/__init__.py b/lib/yunohost/__init__.py index e69de29bb..97cd1f5f3 100755 --- a/lib/yunohost/__init__.py +++ b/lib/yunohost/__init__.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +""" YunoHost scripts for the moulinette """ + +""" License + + Copyright (C) 2015 YUNOHOST.ORG + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, see http://www.gnu.org/licenses + +""" + +## Packages versions + +def get_version(package): + from moulinette.utils import process + return process.check_output( + "dpkg-query -W -f='${{Version}}' {0}".format(package) + ).strip() + +def get_versions(*args, **kwargs): + from collections import OrderedDict + return OrderedDict([ + ('moulinette', get_version('moulinette')), + ('moulinette-yunohost', get_version('moulinette-yunohost')), + ('yunohost-admin', get_version('yunohost-admin')), + ]) From 8cd95410bea5d1f25e5791d089bce68dc07ce3c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Mon, 13 Jul 2015 17:51:17 +0200 Subject: [PATCH 02/36] [fix] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e4fc7d9e5..a95de2512 100644 --- a/.gitignore +++ b/.gitignore @@ -5,11 +5,11 @@ *.egg-info *.swp *.swo +*~ dist build eggs parts -bin cache var sdist From a336f33276097e7bc2732802206c9a0b592e63c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Mon, 13 Jul 2015 22:46:38 +0200 Subject: [PATCH 03/36] [fix] Allow empty app arguments in app_install --- lib/yunohost/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index 73498ca9e..5972b2d37 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -469,7 +469,7 @@ def app_install(auth, app, label=None, args=None): try: if args is None: args = '' - args_dict = dict(urlparse.parse_qsl(args)) + args_dict = dict(urlparse.parse_qsl(args, keep_blank_values=True)) except: args_dict = {} From fd5eefef79c99add38a6252951d84eb2ab42e4f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Tue, 14 Jul 2015 22:14:57 +0200 Subject: [PATCH 04/36] [fix] Invalidate passwd at user creation/deletion (fix #70) --- lib/yunohost/user.py | 27 ++++++++++++++++++++++----- locales/en.json | 1 + 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/lib/yunohost/user.py b/lib/yunohost/user.py index 15310346f..897b53d34 100644 --- a/lib/yunohost/user.py +++ b/lib/yunohost/user.py @@ -24,7 +24,6 @@ Manage users """ import os -import sys import crypt import random import string @@ -35,6 +34,9 @@ import math import re from moulinette.core import MoulinetteError +from moulinette.utils.log import getActionLogger + +logger = getActionLogger('yunohost.user') def user_list(auth, fields=None, filter=None, limit=None, offset=None): @@ -141,7 +143,7 @@ def user_create(auth, username, firstname, lastname, mail, password, char_set = string.ascii_uppercase + string.digits salt = ''.join(random.sample(char_set,8)) salt = '$1$' + salt + '$' - pwd = '{CRYPT}' + crypt.crypt(str(password), salt) + user_pwd = '{CRYPT}' + crypt.crypt(str(password), salt) attr_dict = { 'objectClass' : ['mailAccount', 'inetOrgPerson', 'posixAccount'], 'givenName' : firstname, @@ -152,7 +154,7 @@ def user_create(auth, username, firstname, lastname, mail, password, 'mail' : mail, 'maildrop' : username, 'mailuserquota' : mailbox_quota, - 'userPassword' : pwd, + 'userPassword' : user_pwd, 'gidNumber' : uid, 'uidNumber' : uid, 'homeDirectory' : '/home/' + username, @@ -186,11 +188,23 @@ def user_create(auth, username, firstname, lastname, mail, password, if auth.add(rdn, attr_dict): + # Invalidate passwd to take user creation into account + subprocess.call(['nscd', '-i', 'passwd']) + # Update SFTP user group memberlist = auth.search(filter='cn=sftpusers', attrs=['memberUid'])[0]['memberUid'] memberlist.append(username) if auth.update('cn=sftpusers,ou=groups', { 'memberUid': memberlist }): - os.system("su - %s -c ''" % username) + try: + # Attempt to create user home folder + subprocess.check_call( + ['su', '-', username, '-c', "''"]) + except subprocess.CalledProcessError: + if not os.path.isdir('/home/{0}'.format(username)): + logger.exception('cannot create user home folder') + msignals.display( + m18n.n('user_home_creation_failed'), 'warning') + app_ssowatconf(auth) #TODO: Send a welcome mail to user msignals.display(m18n.n('user_created'), 'success') @@ -215,13 +229,16 @@ def user_delete(auth, username, purge=False): from yunohost.hook import hook_callback if auth.remove('uid=%s,ou=users' % username): + # Invalidate passwd to take user deletion into account + subprocess.call(['nscd', '-i', 'passwd']) + # Update SFTP user group memberlist = auth.search(filter='cn=sftpusers', attrs=['memberUid'])[0]['memberUid'] try: memberlist.remove(username) except: pass if auth.update('cn=sftpusers,ou=groups', { 'memberUid': memberlist }): if purge: - os.system('rm -rf /home/%s' % username) + subprocess.call(['rm', '-rf', '/home/{0}'.format(username)]) else: raise MoulinetteError(169, m18n.n('user_deletion_failed')) diff --git a/locales/en.json b/locales/en.json index c0d89a7b0..64cfd7b4e 100644 --- a/locales/en.json +++ b/locales/en.json @@ -169,6 +169,7 @@ "user_update_failed" : "Unable to update user", "user_updated" : "User successfully updated", "user_info_failed" : "Unable to retrieve user information", + "user_home_creation_failed" : "Unable to create user home folder", "admin_password" : "Administration password", "ask_firstname" : "First name", From eda7e178adcfa6b961456380a6d0c712c2c800e9 Mon Sep 17 00:00:00 2001 From: M5oul Date: Wed, 15 Jul 2015 15:28:09 +0200 Subject: [PATCH 05/36] Add AGPL license --- LICENSE | 661 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 661 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..dbbe35581 --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. From aec3986514094725552e9ebe8c80acb86bbcea3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Sat, 18 Jul 2015 16:41:58 +0200 Subject: [PATCH 06/36] [fix] Add minimum moulinette version in debian/control --- .gitignore | 3 +++ debian/control | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a95de2512..726bba63a 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ pip-log.txt # Mr Developer .mr.developer.cfg + +# moulinette lib +lib/yunohost/locales diff --git a/debian/control b/debian/control index a5f7bb639..6010b2971 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,7 @@ Homepage: https://yunohost.org/ Package: moulinette-yunohost Architecture: all -Depends: moulinette, +Depends: moulinette (>= 2.2.1), python-psutil, python-requests, glances, From 62620a58cf74824e3e9a76ba1ce818db0b5c84e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Sat, 18 Jul 2015 16:43:16 +0200 Subject: [PATCH 07/36] Update changelog for 2.2.3 release --- debian/changelog | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/debian/changelog b/debian/changelog index d264c81d4..75e5da8ab 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +moulinette-yunohost (2.2.3) stable; urgency=low + + * [fix] Catch proper exception in backup_list (fix #65) + * [fix] Display YunoHost packages versions (fix #11) + * [fix] Allow empty app arguments in app_install + * [fix] Invalidate passwd at user creation/deletion (fix #70) + * [fix] Add minimum moulinette version in debian/control + + -- Jérôme Lebleu Sat, 18 Jul 2015 16:42:59 +0200 + moulinette-yunohost (2.2.2) stable; urgency=low * [fix] Avoid cd errors From feef2829560af8d25d084e252766d957efa35615 Mon Sep 17 00:00:00 2001 From: ZeHiro Date: Tue, 21 Jul 2015 11:53:58 +0200 Subject: [PATCH 08/36] [fix] Fix skipped_urls for each domain and #68 Fixes https://github.com/YunoHost/moulinette-yunohost/issues/68 --- lib/yunohost/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index 73498ca9e..4952097d2 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -928,7 +928,7 @@ def app_ssowatconf(auth): redirected_regex.update(app_settings['redirected_regex']) for domain in domains: - skipped_urls.extend(['/yunohost/admin', '/yunohost/api']) + skipped_urls.extend([domain + '/yunohost/admin', domain + '/yunohost/api']) conf_dict = { 'portal_domain': main_domain, From 341aaaa9050a12c6618da5370ced22da6467d203 Mon Sep 17 00:00:00 2001 From: nahoj Date: Sat, 25 Jul 2015 14:43:14 +0200 Subject: [PATCH 09/36] typo --- data/actionsmap/yunohost.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 7f3ae9483..774ce33fe 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -437,7 +437,7 @@ app: ### app_setting() setting: - action_help: Set ou get an app setting value + action_help: Set or get an app setting value api: GET /apps//settings arguments: app: From 475b3bb110a0347f1cf93656830fac3e918b765e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Mon, 27 Jul 2015 08:39:14 +0200 Subject: [PATCH 10/36] [fix] Correct logger object in backup_list (fix #75) --- lib/yunohost/backup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yunohost/backup.py b/lib/yunohost/backup.py index 4b072d11f..7f98b118d 100644 --- a/lib/yunohost/backup.py +++ b/lib/yunohost/backup.py @@ -299,7 +299,7 @@ def backup_list(): # Retrieve local archives archives = os.listdir(archives_path) except OSError as e: - logging.info("unable to iterate over local archives: %s", str(e)) + logger.info("unable to iterate over local archives: %s", str(e)) else: # Iterate over local archives for f in archives: From ca9da64d1abcf1e394f3230305e8840a7f4c2f29 Mon Sep 17 00:00:00 2001 From: zamentur Date: Sun, 9 Aug 2015 15:00:13 +0200 Subject: [PATCH 11/36] [fix] 2nd installation of apps with a hooks directory --- lib/yunohost/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index 94f91f23f..421e017d3 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -433,7 +433,7 @@ def app_install(auth, app, label=None, args=None): if 'hooks' in os.listdir(app_tmp_folder): for hook in os.listdir(app_tmp_folder +'/hooks'): #TODO: do it with sed ? - if file[:1] != '.': + if hook[:1] != '.': with open(app_tmp_folder +'/hooks/'+ hook, "r") as sources: lines = sources.readlines() with open(app_tmp_folder +'/hooks/'+ hook, "w") as sources: From e0b4ecfe39337fbdea1b7d8e7e3f6e3434ab3bb4 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Thu, 3 Sep 2015 13:56:25 +0200 Subject: [PATCH 12/36] Add helper bash functions for apps developers --- data/apps/helpers | 7 +++++++ data/apps/helpers.d/password | 3 +++ debian/install | 1 + 3 files changed, 11 insertions(+) create mode 100644 data/apps/helpers create mode 100644 data/apps/helpers.d/password diff --git a/data/apps/helpers b/data/apps/helpers new file mode 100644 index 000000000..7473c96cc --- /dev/null +++ b/data/apps/helpers @@ -0,0 +1,7 @@ +# -*- shell-script -*- + +# TODO : use --regex to validate against a namespace +for helper in $(run-parts --list /usr/share/yunohost/apps/helpers.d 2>/dev/null) ; do + [ -r $helper ] && . $helper || true +done + diff --git a/data/apps/helpers.d/password b/data/apps/helpers.d/password new file mode 100644 index 000000000..0087921c4 --- /dev/null +++ b/data/apps/helpers.d/password @@ -0,0 +1,3 @@ +ynh_password() { + echo $(dd if=/dev/urandom bs=1 count=200 2> /dev/null | tr -c -d '[A-Za-z0-9]' | sed -n 's/\(.\{24\}\).*/\1/p') +} diff --git a/debian/install b/debian/install index 405448e5d..4c91fbd4e 100644 --- a/debian/install +++ b/debian/install @@ -2,5 +2,6 @@ bin/* /usr/bin/ data/actionsmap/* /usr/share/moulinette/actionsmap/ data/hooks/* /usr/share/yunohost/hooks/ data/other/* /usr/share/yunohost/yunohost-config/moulinette/ +data/apps/* /usr/share/yunohost/apps/ lib/yunohost/*.py /usr/lib/moulinette/yunohost/ locales/* /usr/lib/moulinette/yunohost/locales/ From 42fa6a3c325f32fcd8654255b7dfe7c1f3ce4d97 Mon Sep 17 00:00:00 2001 From: opi Date: Thu, 3 Sep 2015 14:24:50 +0200 Subject: [PATCH 13/36] [enh] Add ynh_user_exists helper. --- data/apps/helpers.d/user_exists | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 data/apps/helpers.d/user_exists diff --git a/data/apps/helpers.d/user_exists b/data/apps/helpers.d/user_exists new file mode 100644 index 000000000..662036f55 --- /dev/null +++ b/data/apps/helpers.d/user_exists @@ -0,0 +1,3 @@ +ynh_user_exists() { + sudo yunohost user list --json | grep -q "\"username\": \"${1}\"" +} \ No newline at end of file From 441b89f0480ce6cec4dc2d9fe5c68d5d349edbf5 Mon Sep 17 00:00:00 2001 From: opi Date: Thu, 3 Sep 2015 14:36:27 +0200 Subject: [PATCH 14/36] [fix] Use one file for all user related helpers. --- data/apps/helpers.d/{user_exists => user} | 2 ++ 1 file changed, 2 insertions(+) rename data/apps/helpers.d/{user_exists => user} (76%) diff --git a/data/apps/helpers.d/user_exists b/data/apps/helpers.d/user similarity index 76% rename from data/apps/helpers.d/user_exists rename to data/apps/helpers.d/user index 662036f55..de9a2cbce 100644 --- a/data/apps/helpers.d/user_exists +++ b/data/apps/helpers.d/user @@ -1,3 +1,5 @@ + +# Check if a user exists ynh_user_exists() { sudo yunohost user list --json | grep -q "\"username\": \"${1}\"" } \ No newline at end of file From 71c94f8aef3a9601ce0f9b64974d689dd6c5ee9e Mon Sep 17 00:00:00 2001 From: Adrien Beudin Date: Thu, 3 Sep 2015 16:39:21 +0200 Subject: [PATCH 15/36] [fix] add netcat-openbsd packages in depends --- debian/control | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 6010b2971..ee8391364 100644 --- a/debian/control +++ b/debian/control @@ -18,6 +18,7 @@ Depends: moulinette (>= 2.2.1), bind9utils, python-apt, ca-certificates, - python-dnspython + python-dnspython, + netcat-openbsd Description: YunoHost Python scripts Python functions to manage a YunoHost instance From f8eced728c78712a7c2a402bfe3e33e9bd1385f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Tue, 8 Sep 2015 14:20:05 +0200 Subject: [PATCH 16/36] Update changelog for 2.3.0 release --- debian/changelog | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/debian/changelog b/debian/changelog index 75e5da8ab..34a8b9ebf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,32 @@ +moulinette-yunohost (2.3.0) testing; urgency=low + + [ M5oul ] + * Add AGPL license + + [ ZeHiro ] + * [fix] Fix skipped_urls for each domain and #68 + + [ nahoj ] + * typo + + [ Jérôme Lebleu ] + * [fix] Correct logger object in backup_list (fix #75) + + [ zamentur ] + * [fix] 2nd installation of apps with a hooks directory + + [ Julien Malik ] + * Add helper bash functions for apps developers + + [ opi ] + * [enh] Add ynh_user_exists helper. + * [fix] Use one file for all user related helpers. + + [ Adrien Beudin ] + * [fix] add netcat-openbsd packages in depends + + -- Jérôme Lebleu Tue, 08 Sep 2015 14:19:28 +0200 + moulinette-yunohost (2.2.3) stable; urgency=low * [fix] Catch proper exception in backup_list (fix #65) From cb557c1a2139ecb347ef1a20a672046f32713942 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:34:54 +0200 Subject: [PATCH 17/36] [fix] Indent postinst script uniformly --- debian/postinst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/debian/postinst b/debian/postinst index 2ad815792..279301c20 100644 --- a/debian/postinst +++ b/debian/postinst @@ -4,21 +4,21 @@ TMP=/usr/share/yunohost/yunohost-config/moulinette if [ ! -d /etc/yunohost ]; then - mkdir -p /etc/yunohost + mkdir -p /etc/yunohost fi # Allow users to access /media directory if [ ! -d /etc/skel/media ]; then - mkdir -p /media - ln -s /media /etc/skel/ + mkdir -p /media + ln -s /media /etc/skel/ fi #Firewall grep -q "UPNP:" /etc/yunohost/firewall.yml > /dev/null 2>&1 if [[ $? -eq 0 ]] || [ ! -f /etc/yunohost/firewall.yml ]; then - cp $TMP/firewall.yml /etc/yunohost/ + cp $TMP/firewall.yml /etc/yunohost/ fi # App fetchlist @@ -30,7 +30,7 @@ fi # Service list if [ ! -f /etc/yunohost/services.yml ]; then - cp $TMP/services.yml /etc/yunohost/ + cp $TMP/services.yml /etc/yunohost/ fi # Stop old API From de6c2858d10d1c3a08cc5f21295388dd4aedcc7e Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:37:52 +0200 Subject: [PATCH 18/36] [enh] postinst : only respond to configure --- debian/postinst | 121 ++++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 46 deletions(-) diff --git a/debian/postinst b/debian/postinst index 279301c20..564c9e1eb 100644 --- a/debian/postinst +++ b/debian/postinst @@ -1,56 +1,85 @@ #!/bin/bash +#!/bin/sh +# postinst script for yunohost-config-metronome -TMP=/usr/share/yunohost/yunohost-config/moulinette +set -e -if [ ! -d /etc/yunohost ]; -then - mkdir -p /etc/yunohost -fi +do_configure() { + TMP=/usr/share/yunohost/yunohost-config/moulinette -# Allow users to access /media directory -if [ ! -d /etc/skel/media ]; -then - mkdir -p /media - ln -s /media /etc/skel/ -fi + if [ ! -d /etc/yunohost ]; + then + mkdir -p /etc/yunohost + fi -#Firewall -grep -q "UPNP:" /etc/yunohost/firewall.yml > /dev/null 2>&1 -if [[ $? -eq 0 ]] || [ ! -f /etc/yunohost/firewall.yml ]; -then - cp $TMP/firewall.yml /etc/yunohost/ -fi + # Allow users to access /media directory + if [ ! -d /etc/skel/media ]; + then + mkdir -p /media + ln -s /media /etc/skel/ + fi -# App fetchlist -if [ -f /etc/cron.d/yunohost-applist-yunohost ]; -then - sed -i "s/--no-ldap //g" /etc/cron.d/yunohost-applist-yunohost -fi + #Firewall + grep -q "UPNP:" /etc/yunohost/firewall.yml > /dev/null 2>&1 + if [[ $? -eq 0 ]] || [ ! -f /etc/yunohost/firewall.yml ]; + then + cp $TMP/firewall.yml /etc/yunohost/ + fi -# Service list -if [ ! -f /etc/yunohost/services.yml ]; -then - cp $TMP/services.yml /etc/yunohost/ -fi + # App fetchlist + if [ -f /etc/cron.d/yunohost-applist-yunohost ]; + then + sed -i "s/--no-ldap //g" /etc/cron.d/yunohost-applist-yunohost + fi -# Stop old API -ps aux | grep "yunohost.tac" | grep -qv grep -if [[ $? -eq 0 ]]; -then - killall twistd -fi + # Service list + if [ ! -f /etc/yunohost/services.yml ]; + then + cp $TMP/services.yml /etc/yunohost/ + fi -rm -rf /var/cache/moulinette/* -update-rc.d yunohost-api defaults -service yunohost-api restart + # Stop old API + ps aux | grep "yunohost.tac" | grep -qv grep + if [[ $? -eq 0 ]]; + then + killall twistd + fi -# Reload SSOwat conf if obsolete -if [ -f /etc/yunohost/installed ]; -then - yunohost firewall upnp | grep -qi "true" - if [[ $? -eq 0 ]]; - then - yunohost firewall upnp enable - fi - yunohost app ssowatconf -fi + rm -rf /var/cache/moulinette/* + update-rc.d yunohost-api defaults + service yunohost-api restart + + # Reload SSOwat conf if obsolete + if [ -f /etc/yunohost/installed ]; + then + yunohost firewall upnp | grep -qi "true" + if [[ $? -eq 0 ]]; + then + yunohost firewall upnp enable + fi + yunohost app ssowatconf + fi +} + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + +case "$1" in + configure) + do_configure + ;; + abort-upgrade|abort-remove|abort-deconfigure) + ;; + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac From 7a4edd2bc2ae9c766498bd3a49a4fc617161c2bc Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:39:29 +0200 Subject: [PATCH 19/36] [lintian] fix output-of-updaterc.d-not-redirected-to-dev-null yunohost-api postinst --- debian/postinst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/postinst b/debian/postinst index 564c9e1eb..9b04e93e7 100644 --- a/debian/postinst +++ b/debian/postinst @@ -46,7 +46,7 @@ do_configure() { fi rm -rf /var/cache/moulinette/* - update-rc.d yunohost-api defaults + update-rc.d yunohost-api defaults > /dev/null service yunohost-api restart # Reload SSOwat conf if obsolete From 06e667b71a0d7d9f5dcaf53236c4dde63023bfa8 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:45:16 +0200 Subject: [PATCH 20/36] [lintian] fix postrm-contains-additional-updaterc.d-calls etc/init.d/yunohost-firewall --- debian/postinst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/debian/postinst b/debian/postinst index 9b04e93e7..9a537a19f 100644 --- a/debian/postinst +++ b/debian/postinst @@ -49,6 +49,9 @@ do_configure() { update-rc.d yunohost-api defaults > /dev/null service yunohost-api restart + # Firewall + update-rc.d yunohost-firewall defaults > /dev/null + # Reload SSOwat conf if obsolete if [ -f /etc/yunohost/installed ]; then From e57a4533b4526e059c31a115ffcc9c59241bd3e2 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:54:58 +0200 Subject: [PATCH 21/36] [lintian] fix init.d-script-missing-lsb-description --- debian/yunohost-api.init | 1 + debian/yunohost-firewall.init | 1 + 2 files changed, 2 insertions(+) diff --git a/debian/yunohost-api.init b/debian/yunohost-api.init index 11c92b747..2bd0222b2 100755 --- a/debian/yunohost-api.init +++ b/debian/yunohost-api.init @@ -6,6 +6,7 @@ # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start/stop YunoHost API +# Description: Start/stop YunoHost API ### END INIT INFO DAEMON=/usr/bin/yunohost-api diff --git a/debian/yunohost-firewall.init b/debian/yunohost-firewall.init index f16e1d6b4..06bf2145c 100755 --- a/debian/yunohost-firewall.init +++ b/debian/yunohost-firewall.init @@ -6,6 +6,7 @@ # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start/stop YunoHost firewall +# Description: Start/stop YunoHost firewall ### END INIT INFO DAEMON=/usr/bin/yunohost From fe8c909f05d3e093cd09394ff23c596fc1d57a46 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:58:50 +0200 Subject: [PATCH 22/36] [lintian] fix init.d-script-does-not-implement-required-option etc/init.d/yunohost-api force-reload --- debian/yunohost-api.init | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/yunohost-api.init b/debian/yunohost-api.init index 2bd0222b2..3e75e159d 100755 --- a/debian/yunohost-api.init +++ b/debian/yunohost-api.init @@ -41,7 +41,7 @@ case "$1" in kill `ps aux | grep 'yunohost-api' | grep -v grep | grep -v stop | awk '{print $2}'` > /dev/null 2>&1 log_end_msg 0 ;; - restart) + restart|force-reload) logger "YunoHost API: Restarting" log_daemon_msg "Restarting API: YunoHost" if [ -f /var/run/yunohost-api.pid ]; then @@ -67,7 +67,7 @@ case "$1" in ;; *) logger "YunoHost API: Invalid usage" - echo "Usage: /etc/init.d/yunohost-api {start|stop|restart|status}" >&2 + echo "Usage: /etc/init.d/yunohost-api {start|stop|restart|force-reload|status}" >&2 exit 1 ;; esac From 2ccfe335a5817d82671d8487f878312c24b0ddae Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:59:49 +0200 Subject: [PATCH 23/36] [lintian] fix init.d-script-does-not-implement-required-option etc/init.d/yunohost-firewall force-reload --- debian/yunohost-firewall.init | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/yunohost-firewall.init b/debian/yunohost-firewall.init index 06bf2145c..fd1443494 100755 --- a/debian/yunohost-firewall.init +++ b/debian/yunohost-firewall.init @@ -31,7 +31,7 @@ case "$1" in /usr/bin/yunohost firewall stop log_end_msg $? ;; - restart) + restart|force-reload) logger "YunoHost firewall: Restarting" log_daemon_msg "Restarting firewall: YunoHost" /usr/bin/yunohost firewall reload @@ -45,7 +45,7 @@ case "$1" in ;; *) logger "YunoHost API: Invalid usage" - echo "Usage: /etc/init.d/yunohost-api {start|stop|restart|status}" >&2 + echo "Usage: /etc/init.d/yunohost-api {start|stop|restart|force-reload|status}" >&2 exit 1 ;; esac From 4a4f106f15790db49dded60432338f250fddf83e Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 19:07:47 +0200 Subject: [PATCH 24/36] [lintian] fix executable-not-elf-or-script usr/lib/moulinette/yunohost/__init__.py --- lib/yunohost/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 lib/yunohost/__init__.py diff --git a/lib/yunohost/__init__.py b/lib/yunohost/__init__.py old mode 100755 new mode 100644 From ce4c54ad88cc1c332fd7368e900c7a696d2243b6 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 19:12:01 +0200 Subject: [PATCH 25/36] [lintian] fix script-not-executable for backup/restore hooks --- data/hooks/backup/05-system_ldap | 2 -- data/hooks/backup/08-system_ssh | 2 -- data/hooks/backup/11-system_mysql | 2 -- data/hooks/backup/14-system_ssowat | 2 -- data/hooks/backup/17-system_home | 2 -- data/hooks/backup/20-system_yunohost | 2 -- data/hooks/backup/23-system_mail | 2 -- data/hooks/backup/26-system_xmpp | 2 -- data/hooks/backup/29-system_nginx | 2 -- data/hooks/backup/32-system_cron | 2 -- data/hooks/restore/05-system_ldap | 2 -- data/hooks/restore/08-system_ssh | 2 -- data/hooks/restore/11-system_mysql | 2 -- data/hooks/restore/14-system_ssowat | 2 -- data/hooks/restore/17-system_home | 2 -- data/hooks/restore/20-system_yunohost | 2 -- data/hooks/restore/23-system_mail | 2 -- data/hooks/restore/26-system_xmpp | 2 -- data/hooks/restore/29-system_nginx | 2 -- data/hooks/restore/32-system_cron | 2 -- 20 files changed, 40 deletions(-) diff --git a/data/hooks/backup/05-system_ldap b/data/hooks/backup/05-system_ldap index 65c52fc79..9ef09b114 100644 --- a/data/hooks/backup/05-system_ldap +++ b/data/hooks/backup/05-system_ldap @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ldap" mkdir -p $backup_dir diff --git a/data/hooks/backup/08-system_ssh b/data/hooks/backup/08-system_ssh index 617eee0f2..e5f2570ea 100644 --- a/data/hooks/backup/08-system_ssh +++ b/data/hooks/backup/08-system_ssh @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ssh" mkdir -p $backup_dir diff --git a/data/hooks/backup/11-system_mysql b/data/hooks/backup/11-system_mysql index e5ff07c52..984d52a61 100644 --- a/data/hooks/backup/11-system_mysql +++ b/data/hooks/backup/11-system_mysql @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/mysql" mkdir -p $backup_dir diff --git a/data/hooks/backup/14-system_ssowat b/data/hooks/backup/14-system_ssowat index f4ec8c428..fbb78f196 100644 --- a/data/hooks/backup/14-system_ssowat +++ b/data/hooks/backup/14-system_ssowat @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ssowat" mkdir -p $backup_dir diff --git a/data/hooks/backup/17-system_home b/data/hooks/backup/17-system_home index 13414a755..b73b2dff3 100644 --- a/data/hooks/backup/17-system_home +++ b/data/hooks/backup/17-system_home @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/home" mkdir -p $backup_dir diff --git a/data/hooks/backup/20-system_yunohost b/data/hooks/backup/20-system_yunohost index 22d556c61..e49b52899 100644 --- a/data/hooks/backup/20-system_yunohost +++ b/data/hooks/backup/20-system_yunohost @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/yunohost" mkdir -p $backup_dir diff --git a/data/hooks/backup/23-system_mail b/data/hooks/backup/23-system_mail index 2145c0bc4..7fe210ce2 100644 --- a/data/hooks/backup/23-system_mail +++ b/data/hooks/backup/23-system_mail @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/mail" sudo cp -a /var/mail/. $backup_dir diff --git a/data/hooks/backup/26-system_xmpp b/data/hooks/backup/26-system_xmpp index 836c73078..2b87644d2 100644 --- a/data/hooks/backup/26-system_xmpp +++ b/data/hooks/backup/26-system_xmpp @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/xmpp" mkdir -p $backup_dir/{etc,var} diff --git a/data/hooks/backup/29-system_nginx b/data/hooks/backup/29-system_nginx index 6bbcae2c1..976809122 100644 --- a/data/hooks/backup/29-system_nginx +++ b/data/hooks/backup/29-system_nginx @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/nginx" mkdir -p $backup_dir diff --git a/data/hooks/backup/32-system_cron b/data/hooks/backup/32-system_cron index b529b0216..87a2a4f2e 100644 --- a/data/hooks/backup/32-system_cron +++ b/data/hooks/backup/32-system_cron @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/cron" mkdir -p $backup_dir diff --git a/data/hooks/restore/05-system_ldap b/data/hooks/restore/05-system_ldap index 58ca04ea9..f16225c3e 100644 --- a/data/hooks/restore/05-system_ldap +++ b/data/hooks/restore/05-system_ldap @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ldap" if [ -z "$2" ]; then diff --git a/data/hooks/restore/08-system_ssh b/data/hooks/restore/08-system_ssh index 09aaf9c9a..bfe729f3f 100644 --- a/data/hooks/restore/08-system_ssh +++ b/data/hooks/restore/08-system_ssh @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ssh" sudo cp -a $backup_dir/. /etc/ssh diff --git a/data/hooks/restore/11-system_mysql b/data/hooks/restore/11-system_mysql index 28db51483..23293b153 100644 --- a/data/hooks/restore/11-system_mysql +++ b/data/hooks/restore/11-system_mysql @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/mysql" mysqlpwd=$(sudo cat /etc/yunohost/mysql) diff --git a/data/hooks/restore/14-system_ssowat b/data/hooks/restore/14-system_ssowat index df92fe10e..15bae3c77 100644 --- a/data/hooks/restore/14-system_ssowat +++ b/data/hooks/restore/14-system_ssowat @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ssowat" sudo cp -a $backup_dir/. /etc/ssowat diff --git a/data/hooks/restore/17-system_home b/data/hooks/restore/17-system_home index a90794ad6..d005bed07 100644 --- a/data/hooks/restore/17-system_home +++ b/data/hooks/restore/17-system_home @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/home" sudo cp -a $backup_dir/. /home diff --git a/data/hooks/restore/20-system_yunohost b/data/hooks/restore/20-system_yunohost index 1bd332763..2ceb2ada6 100644 --- a/data/hooks/restore/20-system_yunohost +++ b/data/hooks/restore/20-system_yunohost @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/yunohost" sudo cp -a $backup_dir/. /etc/yunohost diff --git a/data/hooks/restore/23-system_mail b/data/hooks/restore/23-system_mail index 39f6f933f..ecef0ec15 100644 --- a/data/hooks/restore/23-system_mail +++ b/data/hooks/restore/23-system_mail @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/mail" sudo cp -a $backup_dir/. /var/mail diff --git a/data/hooks/restore/26-system_xmpp b/data/hooks/restore/26-system_xmpp index c1b4e360e..70dc7e1c4 100644 --- a/data/hooks/restore/26-system_xmpp +++ b/data/hooks/restore/26-system_xmpp @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/xmpp" sudo cp -a $backup_dir/etc/. /etc/metronome diff --git a/data/hooks/restore/29-system_nginx b/data/hooks/restore/29-system_nginx index 62810985b..5ffaf5c14 100644 --- a/data/hooks/restore/29-system_nginx +++ b/data/hooks/restore/29-system_nginx @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/nginx" sudo cp -a $backup_dir/. /etc/nginx/conf.d diff --git a/data/hooks/restore/32-system_cron b/data/hooks/restore/32-system_cron index b1a53c3d0..1e12d23b7 100644 --- a/data/hooks/restore/32-system_cron +++ b/data/hooks/restore/32-system_cron @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/cron" sudo cp -a $backup_dir/. /etc/cron.d From 772c974852d130854ddc507900d336743cfdc237 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Thu, 10 Sep 2015 11:30:08 +0200 Subject: [PATCH 26/36] [fix] remove copy-pasted comments --- debian/postinst | 2 -- 1 file changed, 2 deletions(-) diff --git a/debian/postinst b/debian/postinst index 9a537a19f..3106cfed8 100644 --- a/debian/postinst +++ b/debian/postinst @@ -1,6 +1,4 @@ #!/bin/bash -#!/bin/sh -# postinst script for yunohost-config-metronome set -e From fb706bf6bfdc9d04ca1926c63b033098a387b309 Mon Sep 17 00:00:00 2001 From: Le Kload Date: Tue, 22 Sep 2015 17:32:13 +0200 Subject: [PATCH 27/36] [fix] Ensure that arguments are passed to the hook as string --- lib/yunohost/hook.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/yunohost/hook.py b/lib/yunohost/hook.py index ccfd242b8..635800e31 100644 --- a/lib/yunohost/hook.py +++ b/lib/yunohost/hook.py @@ -303,6 +303,7 @@ def hook_exec(file, args=None): if arg_list: # Concatenate arguments and escape them with double quotes to prevent # bash related issue if an argument is empty and is not the last + arg_list = [str(s) for s in arg_list] arg_str = '\\"{:s}\\"'.format('\\" \\"'.join(arg_list)) msignals.display(m18n.n('executing_script')) From d60e7fb1b61b1916f7a2841c176a0a4e3617a514 Mon Sep 17 00:00:00 2001 From: opi Date: Tue, 22 Sep 2015 19:53:59 +0200 Subject: [PATCH 28/36] [fix] Use SSL/TLS to fetch app list for christ's sake --- lib/yunohost/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index 421e017d3..d8b1b7b7a 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -66,7 +66,7 @@ def app_fetchlist(url=None, name=None): Keyword argument: name -- Name of the list (default yunohost) - url -- URL of remote JSON list (default http://app.yunohost.org/list.json) + url -- URL of remote JSON list (default https://app.yunohost.org/list.json) """ # Create app path if not exists @@ -74,7 +74,7 @@ def app_fetchlist(url=None, name=None): except OSError: os.makedirs(repo_path) if url is None: - url = 'http://app.yunohost.org/list.json' + url = 'https://app.yunohost.org/list.json' name = 'yunohost' else: if name is None: From 47d8b7f8af8fe1cb3dd221701424befd31ebbc7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Sat, 26 Sep 2015 22:17:30 +0200 Subject: [PATCH 29/36] [fix] Replace bind9 by dnsmasq in services definition --- data/other/services.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/other/services.yml b/data/other/services.yml index 59fe141d5..c183be54c 100644 --- a/data/other/services.yml +++ b/data/other/services.yml @@ -4,7 +4,7 @@ nginx: avahi-daemon: status: service log: /var/log/daemon.log -bind9: +dnsmasq: status: service log: /var/log/daemon.log dovecot: From 1ceb1259bc5f65cc94ce7447aa71117f9ad33dd2 Mon Sep 17 00:00:00 2001 From: kload Date: Sat, 26 Sep 2015 22:28:49 +0200 Subject: [PATCH 30/36] [fix] IPv6 record in DynDNS --- data/actionsmap/yunohost.yml | 3 ++ lib/yunohost/dyndns.py | 70 +++++++++++++++++------------------- locales/en.json | 1 + locales/fr.json | 1 + 4 files changed, 37 insertions(+), 38 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 774ce33fe..ef03afcdb 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -1035,6 +1035,9 @@ dyndns: -i: full: --ip help: IP address to send + -6: + full: --ipv6 + help: IPv6 address to send ### dyndns_installcron() installcron: diff --git a/lib/yunohost/dyndns.py b/lib/yunohost/dyndns.py index 27650ad99..4504aaefb 100644 --- a/lib/yunohost/dyndns.py +++ b/lib/yunohost/dyndns.py @@ -85,7 +85,7 @@ def dyndns_subscribe(subscribe_host="dyndns.yunohost.org", domain=None, key=None dyndns_installcron() -def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=None): +def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=None, ipv6=None): """ Update IP on DynDNS platform @@ -94,12 +94,14 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non dyn_host -- Dynette DNS server to inform key -- Public DNS key ip -- IP address to send + ipv6 -- IPv6 address to send """ if domain is None: with open('/etc/yunohost/current_host', 'r') as f: domain = f.readline().rstrip() + # IPv4 if ip is None: try: new_ip = requests.get('http://ip.yunohost.org').text @@ -115,42 +117,22 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non old_ip = '0.0.0.0' # IPv6 - # TODO: Put global IPv6 in the DNS zone instead of ULA - new_ipv6 = None + if ipv6 is None: + try: + new_ipv6 = requests.get('http://ip6.yunohost.org').text + except ConnectionError: + msignals.display(m18n.n('no_ipv6_connectivity'), + 'warning') + else: + new_ipv6 = ipv6 + try: - with open('/etc/yunohost/ipv6') as f: + with open('/etc/yunohost/dyndns/old_ipv6', 'r') as f: old_ipv6 = f.readline().rstrip() except IOError: old_ipv6 = '0000:0000:0000:0000:0000:0000:0000:0000' - try: - # Get the interface - with open('/etc/yunohost/interface') as f: - interface = f.readline().rstrip() - # Get the ULA - with open('/etc/yunohost/ula') as f: - ula = f.readline().rstrip() - # Get the IPv6 address given by radvd and sanitize it - with open('/proc/net/if_inet6') as f: - plain_ula = '' - for hextet in ula.split(':')[0:3]: - if len(hextet) < 4: - hextet = '0000'+ hextet - hextet = hextet[-4:] - plain_ula = plain_ula + hextet - for line in f.readlines(): - if interface in line and plain_ula == line[0:12]: - new_ipv6 = ':'.join([line[0:32][i:i+4] for i in range(0, 32, 4)]) - with open('/etc/yunohost/ipv6', 'w+') as f: - f.write(new_ipv6) - break - except IOError: - pass - - if new_ipv6 is None: - new_ipv6 = '0000:0000:0000:0000:0000:0000:0000:0000' - - if old_ip != new_ip or old_ipv6 != new_ipv6 and new_ipv6 is not None: + if old_ip != new_ip or old_ipv6 != new_ipv6: host = domain.split('.')[1:] host = '.'.join(host) lines = [ @@ -161,22 +143,30 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non 'update delete %s. MX' % domain, 'update delete %s. TXT' % domain, 'update delete pubsub.%s. A' % domain, + 'update delete pubsub.%s. AAAA' % domain, 'update delete muc.%s. A' % domain, + 'update delete muc.%s. AAAA' % domain, 'update delete vjud.%s. A' % domain, + 'update delete vjud.%s. AAAA' % domain, 'update delete _xmpp-client._tcp.%s. SRV' % domain, 'update delete _xmpp-server._tcp.%s. SRV' % domain, 'update add %s. 1800 A %s' % (domain, new_ip), - 'update add %s. 1800 AAAA %s' % (domain, new_ipv6), 'update add %s. 14400 MX 5 %s.' % (domain, domain), 'update add %s. 14400 TXT "v=spf1 a mx -all"' % domain, 'update add pubsub.%s. 1800 A %s' % (domain, new_ip), - 'update add pubsub.%s. 1800 AAAA %s' % (domain, new_ipv6), 'update add muc.%s. 1800 A %s' % (domain, new_ip), - 'update add muc.%s. 1800 AAAA %s' % (domain, new_ipv6), 'update add vjud.%s. 1800 A %s' % (domain, new_ip), - 'update add vjud.%s. 1800 AAAA %s' % (domain, new_ipv6), 'update add _xmpp-client._tcp.%s. 14400 SRV 0 5 5222 %s.' % (domain, domain), - 'update add _xmpp-server._tcp.%s. 14400 SRV 0 5 5269 %s.' % (domain, domain), + 'update add _xmpp-server._tcp.%s. 14400 SRV 0 5 5269 %s.' % (domain, domain) + ] + if new_ipv6 is not None: + lines += [ + 'update add %s. 1800 AAAA %s' % (domain, new_ipv6), + 'update add pubsub.%s. 1800 AAAA %s' % (domain, new_ipv6), + 'update add muc.%s. 1800 AAAA %s' % (domain, new_ipv6), + 'update add vjud.%s. 1800 AAAA %s' % (domain, new_ipv6), + ] + lines += [ 'show', 'send' ] @@ -192,8 +182,12 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non msignals.display(m18n.n('dyndns_ip_updated'), 'success') with open('/etc/yunohost/dyndns/old_ip', 'w') as f: f.write(new_ip) + if new_ipv6 is not None: + with open('/etc/yunohost/dyndns/old_ipv6', 'w') as f: + f.write(new_ipv6) else: - os.system('rm /etc/yunohost/dyndns/old_ip > /dev/null 2>&1') + os.system('rm -f /etc/yunohost/dyndns/old_ip') + os.system('rm -f /etc/yunohost/dyndns/old_ipv6') raise MoulinetteError(errno.EPERM, m18n.n('dyndns_ip_update_failed')) diff --git a/locales/en.json b/locales/en.json index 64cfd7b4e..2d5ff8dd6 100644 --- a/locales/en.json +++ b/locales/en.json @@ -56,6 +56,7 @@ "domain_deletion_failed" : "Unable to delete domain", "domain_deleted" : "Domain successfully deleted", "no_internet_connection": "Server not connected to the Internet", + "no_ipv6_connectivity": "IPv6 connectivity is not available", "dyndns_key_generating" : "DNS key is being generated, it may take a while...", "dyndns_unavailable" : "Unavailable DynDNS subdomain", diff --git a/locales/fr.json b/locales/fr.json index 308d2ee73..d46c4c3e4 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -53,6 +53,7 @@ "domain_deletion_failed": "Impossible de supprimer le domaine", "domain_deleted": "Domaine supprimé avec succès", "no_internet_connection": "Le serveur n'est pas connecté à Internet", + "no_ipv6_connectivity": "IPv6 n'est pas disponible", "dyndns_key_generating": "La clé DNS est en cours de génération, cela peut prendre du temps...", "dyndns_unavailable": "Sous-domaine DynDNS indisponible", "dyndns_registration_failed": "Impossible d'enregistrer le domaine DynDNS : {:s}", From 8e818d54a65b031cc226ff31311446358e342420 Mon Sep 17 00:00:00 2001 From: Jocelyn Delande Date: Sun, 27 Sep 2015 01:14:42 +0200 Subject: [PATCH 31/36] [fix] fix UnboundLocalError on ConnectionError While connecting to ip6.yunohost.org, new_ip6 was not populated if exception. --- lib/yunohost/dyndns.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/yunohost/dyndns.py b/lib/yunohost/dyndns.py index 4504aaefb..67b3db808 100644 --- a/lib/yunohost/dyndns.py +++ b/lib/yunohost/dyndns.py @@ -118,6 +118,7 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non # IPv6 if ipv6 is None: + new_ipv6 = None try: new_ipv6 = requests.get('http://ip6.yunohost.org').text except ConnectionError: From 7c6f2b9373a33f7123d6c674c8e2d1c0b25148e3 Mon Sep 17 00:00:00 2001 From: Jocelyn Delande Date: Sun, 27 Sep 2015 01:16:56 +0200 Subject: [PATCH 32/36] [enh] Determine the public IPv6 locally Avoid depending on a remote service to fetch the globally routable IPv6 address. discussed in #89 --- debian/control | 3 ++- lib/yunohost/dyndns.py | 46 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/debian/control b/debian/control index ee8391364..989cc26b0 100644 --- a/debian/control +++ b/debian/control @@ -19,6 +19,7 @@ Depends: moulinette (>= 2.2.1), python-apt, ca-certificates, python-dnspython, - netcat-openbsd + netcat-openbsd, + iproute2 Description: YunoHost Python scripts Python functions to manage a YunoHost instance diff --git a/lib/yunohost/dyndns.py b/lib/yunohost/dyndns.py index 67b3db808..b4eb376dd 100644 --- a/lib/yunohost/dyndns.py +++ b/lib/yunohost/dyndns.py @@ -26,14 +26,39 @@ import os import sys import requests +import re import json import glob import base64 import errno +import subprocess from moulinette.core import MoulinetteError +class IPRouteLine(object): + """ Utility class to parse an ip route output line + + The output of ip ro is variable and hard to parse completly, it would + require a real parser, not just a regexp, so do minimal parsing here... + + >>> a = IPRouteLine('2001:: from :: via fe80::c23f:fe:1e:cafe dev eth0 src 2000:de:beef:ca:0:fe:1e:cafe metric 0') + >>> a.src_addr + "2000:de:beef:ca:0:fe:1e:cafe" + """ + regexp = re.compile( + r'(?Punreachable)?.*src\s+(?P[0-9a-f:]+).*') + + def __init__(self, line): + self.m = self.regexp.match(line) + if not self.m: + raise ValueError("Not a valid ip route get line") + + # make regexp group available as object attributes + for k, v in self.m.groupdict().items(): + setattr(self, k, v) + + def dyndns_subscribe(subscribe_host="dyndns.yunohost.org", domain=None, key=None): """ Subscribe to a DynDNS service @@ -120,10 +145,23 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non if ipv6 is None: new_ipv6 = None try: - new_ipv6 = requests.get('http://ip6.yunohost.org').text - except ConnectionError: - msignals.display(m18n.n('no_ipv6_connectivity'), - 'warning') + ip_route_out = subprocess.check_output( + ['ip', 'route', 'get', '2000::']).split('\n') + + if len(ip_route_out) > 0: + route = IPRouteLine(ip_route_out[0]) + if not route.unreachable: + new_ipv6 = route.src_addr + + except (OSError, ValueError) as e: + # Unlikely case "ip route" does not return status 0 + # or produces unexpected output + raise MoulinetteError(errno.EBADMSG, + "ip route cmd error : {}".format(e)) + + if new_ipv6 is None: + msignals.display(m18n.n('no_ipv6_connectivity'), 'warning') + else: new_ipv6 = ipv6 From c94ec0610b0b59296649a16de8c131e7165f1a6e Mon Sep 17 00:00:00 2001 From: kload Date: Sun, 27 Sep 2015 10:36:54 +0000 Subject: [PATCH 33/36] Update changelog for 2.3.1 release --- debian/changelog | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/debian/changelog b/debian/changelog index 34a8b9ebf..c8d5a231a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,35 @@ +moulinette-yunohost (2.3.1) testing; urgency=low + + [ Julien Malik ] + * [fix] Indent postinst script uniformly + * [enh] postinst : only respond to configure + * [lintian] fix output-of-updaterc.d-not-redirected-to-dev-null yunohost-api postinst + * [lintian] fix postrm-contains-additional-updaterc.d-calls etc/init.d/yunohost-firewall + * [lintian] fix init.d-script-missing-lsb-description + * [lintian] fix init.d-script-does-not-implement-required-option etc/init.d/yunohost-api force-reload + * [lintian] fix init.d-script-does-not-implement-required-option etc/init.d/yunohost-firewall force-reload + * [lintian] fix executable-not-elf-or-script usr/lib/moulinette/yunohost/__init__.py + * [lintian] fix script-not-executable for backup/restore hooks + * [fix] remove copy-pasted comments + + [ Le Kload ] + * [fix] Ensure that arguments are passed to the hook as string + + [ opi ] + * [fix] Use SSL/TLS to fetch app list + + [ Jérôme Lebleu ] + * [fix] Replace bind9 by dnsmasq in services definition + + [ kload ] + * [fix] IPv6 record in DynDNS + + [ Jocelyn Delande ] + * [fix] fix UnboundLocalError on ConnectionError + * [enh] Determine the public IPv6 locally + + -- kload Sun, 27 Sep 2015 10:36:34 +0000 + moulinette-yunohost (2.3.0) testing; urgency=low [ M5oul ] From c0bb1d7cf1ce1c0c0083233e2ceacbdba9ed78d4 Mon Sep 17 00:00:00 2001 From: Le Kload Date: Mon, 28 Sep 2015 18:55:14 +0200 Subject: [PATCH 34/36] [fix] Compatibility for Jessie and Wheezy --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 989cc26b0..561083c2e 100644 --- a/debian/control +++ b/debian/control @@ -20,6 +20,6 @@ Depends: moulinette (>= 2.2.1), ca-certificates, python-dnspython, netcat-openbsd, - iproute2 + iproute Description: YunoHost Python scripts Python functions to manage a YunoHost instance From c9f79f7420074b9ac56a9b7205efc5e51f5088da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Tue, 29 Sep 2015 14:18:13 +0200 Subject: [PATCH 35/36] [enh] Add a --plain option to the cli for scripting usage --- bin/yunohost | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bin/yunohost b/bin/yunohost index b24fffb77..6800a4a9c 100755 --- a/bin/yunohost +++ b/bin/yunohost @@ -13,6 +13,9 @@ USE_CACHE = True # Either the output has to be encoded as a JSON encoded string or not PRINT_JSON = False +# Either the output has to printed for scripting usage or not +PRINT_PLAIN = False + # Level for which loggers will log LOGGERS_LEVEL = 'INFO' @@ -62,6 +65,10 @@ def _parse_argv(): global PRINT_JSON PRINT_JSON = True argv.remove('--json') + if '--plain' in argv: + global PRINT_PLAIN + PRINT_PLAIN = True + argv.remove('--plain') if '--debug' in argv: global LOGGERS_LEVEL LOGGERS_LEVEL = 'DEBUG' @@ -156,6 +163,6 @@ if __name__ == '__main__': # Execute the action from moulinette import cli - ret = cli(_retrieve_namespaces(), args, - print_json=PRINT_JSON, use_cache=USE_CACHE) + ret = cli(_retrieve_namespaces(), args, use_cache=USE_CACHE, + print_json=PRINT_JSON, print_plain=PRINT_PLAIN) sys.exit(ret) From 444a02b9f9a71fcf0f10311af9bd58f704d5e985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Tue, 29 Sep 2015 18:45:07 +0200 Subject: [PATCH 36/36] [enh] Add app helpers to parse plain command output --- data/apps/helpers.d/user | 14 ++++++++++++-- data/apps/helpers.d/utils | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 data/apps/helpers.d/utils diff --git a/data/apps/helpers.d/user b/data/apps/helpers.d/user index de9a2cbce..1fd8d203c 100644 --- a/data/apps/helpers.d/user +++ b/data/apps/helpers.d/user @@ -1,5 +1,15 @@ - # Check if a user exists +# +# usage: ynh_user_exists username +# | ret: retcode - 0 if user exists, 1 otherwise ynh_user_exists() { sudo yunohost user list --json | grep -q "\"username\": \"${1}\"" -} \ No newline at end of file +} + +# Retrieve a user information +# +# usage: ynh_user_info username key +# | ret: string - the key's value +ynh_user_get_info() { + sudo yunohost user info "${1}" --plain | ynh_get_plain_key "${2}" +} diff --git a/data/apps/helpers.d/utils b/data/apps/helpers.d/utils new file mode 100644 index 000000000..87cd47f6b --- /dev/null +++ b/data/apps/helpers.d/utils @@ -0,0 +1,24 @@ +# Extract a key from a plain command output +# +# usage: ynh_get_plain_key key [subkey [subsubkey ...]] +# | ret: string - the key's value +ynh_get_plain_key() { + prefix="#" + founded=0 + key=$1 + shift + while read line; do + if [[ "$founded" == "1" ]] ; then + [[ "$line" =~ ^${prefix}[^#] ]] && return + echo $line + elif [[ "$line" =~ ^${prefix}${key}$ ]]; then + if [[ -n "$1" ]]; then + prefix+="#" + key=$1 + shift + else + founded=1 + fi + fi + done +}