From b24e63639560afe8a6477c5a8e0a97811367f834 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 25 Aug 2021 17:42:59 +0200 Subject: [PATCH] first commit --- LICENSE | 674 +++++++++++++++++++++++++++++++++ README.md | 61 +++ README_fr.md | 62 +++ check_process | 20 + conf/app.src | 6 + conf/config.js | 262 +++++++++++++ conf/nginx.conf | 26 ++ conf/systemd.service | 16 + doc/.DS_Store | Bin 0 -> 6148 bytes doc/screenshots/screenshot.png | Bin 0 -> 93574 bytes manifest.json | 46 +++ scripts/_common.sh | 26 ++ scripts/backup | 61 +++ scripts/change_url | 135 +++++++ scripts/install | 171 +++++++++ scripts/remove | 84 ++++ scripts/restore | 120 ++++++ scripts/upgrade | 165 ++++++++ 18 files changed, 1935 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 README_fr.md create mode 100644 check_process create mode 100644 conf/app.src create mode 100644 conf/config.js create mode 100644 conf/nginx.conf create mode 100644 conf/systemd.service create mode 100644 doc/.DS_Store create mode 100644 doc/screenshots/screenshot.png create mode 100644 manifest.json create mode 100644 scripts/_common.sh create mode 100644 scripts/backup create mode 100644 scripts/change_url create mode 100644 scripts/install create mode 100644 scripts/remove create mode 100644 scripts/restore create mode 100644 scripts/upgrade diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 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 General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is 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. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + 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. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + 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 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. Use with the GNU Affero General Public License. + + 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 Affero 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 special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 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 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 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 General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + 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 GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..886868f --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# Send for YunoHost + +[![Integration level](https://dash.yunohost.org/integration/send.svg)](https://dash.yunohost.org/appci/app/send) ![](https://ci-apps.yunohost.org/ci/badges/send.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/send.maintain.svg) +[![Install Send with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=send) + +*[Lire ce readme en français.](./README_fr.md)* + +> *This package allows you to install Send quickly and simply on a YunoHost server. +If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.* + +## Overview +HedgeDoc is a real-time collaborative word processing web service. It uses Markdown language. + +**Shipped version:** 3.0.22 + +## Screenshots + +![]() + +## Demo + +* [Official demo]() + +## Configuration + + +## Documentation + + * Official documentation: https://github.com/kiwiirc/kiwiirc/wiki + * YunoHost documentation: + +## YunoHost specific features + +#### Multi-user support + +* Is LDAP supported? **Yes** +* Can the app be used by multiple users? **Yes** + +#### Supported architectures + +* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/send%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/send/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/send%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/send/) + +## Links + + * Report a bug: https://github.com/YunoHost-Apps/send_ynh/issues + * Upstream app repository: https://github.com/mozilla/send + * YunoHost website: https://yunohost.org/ + +--- + +## Developer info + +Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/send_ynh/tree/testing). + +To try the testing branch, please proceed like that. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/send_ynh/tree/testing --debug +or +sudo yunohost app upgrade send -u https://github.com/YunoHost-Apps/send_ynh/tree/testing --debug +``` diff --git a/README_fr.md b/README_fr.md new file mode 100644 index 0000000..c700372 --- /dev/null +++ b/README_fr.md @@ -0,0 +1,62 @@ +# Send pour YunoHost + +[![Niveau d'intégration](https://dash.yunohost.org/integration/send.svg)](https://dash.yunohost.org/appci/app/send) ![](https://ci-apps.yunohost.org/ci/badges/send.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/send.maintain.svg) +[![Installer HedgeDoc avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=send) + +*[Read this readme in english.](./README.md)* + +> *Ce package vous permet d'installer HedgeDoc rapidement et simplement sur un serveur YunoHost. +Si vous n'avez pas YunoHost, consultez [le guide](https://yunohost.org/#/install) pour apprendre comment l'installer.* + +## Vue d'ensemble +HedgeDoc est un service web de traitement de texte collaboratif en temps réel. Il utilise le langage Markdown. + +**Version incluse :** 3.0.22 + +## Captures d'écran + +![]() + +## Démo + +* [Démo officielle]() + +## Configuration + +Vous pouvez configurer HedgeDoc en modifiant le fichier `/var/www/hedgedoc/config.json` et en vous aidant de la [documentation](https://github.com/hedgedoc/server/blob/master/docs/configuration.md) + +## Documentation + + * Documentation officielle : https://github.com/kiwiirc/kiwiirc/wiki + * Documentation YunoHost : + +## Caractéristiques spécifiques YunoHost + +#### Support multi-utilisateur + +* L'authentification LDAP est-elle prise en charge ? **Oui** +* L'application peut-elle être utilisée par plusieurs utilisateurs ? **Oui** + +#### Architectures supportées + +* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/send%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/send/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/send%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/send/) + +## Liens + + * Signaler un bug : https://github.com/YunoHost-Apps/kiwiirc_ynh/issues + * Dépôt de l'application principale : https://github.com/mozilla/send + * Site web YunoHost : https://yunohost.org/ + +--- + +## Informations pour les développeurs + +Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/send_ynh/tree/testing). + +Pour essayer la branche testing, procédez comme suit. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/send_ynh/tree/testing --debug +ou +sudo yunohost app upgrade send -u https://github.com/YunoHost-Apps/send_ynh/tree/testing --debug +``` diff --git a/check_process b/check_process new file mode 100644 index 0000000..f7289e5 --- /dev/null +++ b/check_process @@ -0,0 +1,20 @@ +;; Test complet + ; Manifest + domain="domain.tld" + is_public=1 + ; Checks + pkg_linter=1 + setup_sub_dir=0 + setup_root=1 + setup_nourl=0 + setup_private=1 + setup_public=1 + upgrade=1 + backup_restore=1 + multi_instance=1 + change_url=1 +;;; Options +Email= +Notification=none +;;; Upgrade options + manifest_arg=domain=DOMAIN&is_public=1& \ No newline at end of file diff --git a/conf/app.src b/conf/app.src new file mode 100644 index 0000000..288e2cb --- /dev/null +++ b/conf/app.src @@ -0,0 +1,6 @@ +SOURCE_URL=https://github.com/timvisee/send/archive/refs/tags/v3.4.13.tar.gz +SOURCE_SUM=6b4e072f23325edd47666bdc6edf0e428c5e4ced22d8a5d3ffa9ca12be63b7cb +SOURCE_SUM_PRG=sha256sum +SOURCE_FORMAT=tar.gz +SOURCE_IN_SUBDIR=true +SOURCE_FILENAME= diff --git a/conf/config.js b/conf/config.js new file mode 100644 index 0000000..49c19cd --- /dev/null +++ b/conf/config.js @@ -0,0 +1,262 @@ +const convict = require('convict'); +const { tmpdir } = require('os'); +const path = require('path'); +const { randomBytes } = require('crypto'); + +convict.addFormat({ + name: 'positive-int-array', + coerce: ints => { + // can take: int[] | string[] | string (csv), returns -> int[] + const ints_arr = Array.isArray(ints) ? ints : ints.trim().split(','); + return ints_arr.map(int => + typeof int === 'number' + ? int + : parseInt(int.replace(/['"]+/g, '').trim(), 10) + ); + }, + validate: ints => { + // takes: int[], errors if any NaNs, negatives, or floats present + for (const int of ints) { + if (typeof int !== 'number' || isNaN(int) || int < 0 || int % 1 > 0) + throw new Error('must be a comma-separated list of positive integers'); + } + } +}); + +const conf = convict({ + s3_bucket: { + format: String, + default: '', + env: 'S3_BUCKET' + }, + s3_endpoint: { + format: String, + default: '', + env: 'S3_ENDPOINT' + }, + s3_use_path_style_endpoint: { + format: Boolean, + default: false, + env: 'S3_USE_PATH_STYLE_ENDPOINT' + }, + gcs_bucket: { + format: String, + default: '', + env: 'GCS_BUCKET' + }, + expire_times_seconds: { + format: 'positive-int-array', + default: [300, 3600, 86400, 604800], + env: 'EXPIRE_TIMES_SECONDS' + }, + default_expire_seconds: { + format: Number, + default: 86400, + env: 'DEFAULT_EXPIRE_SECONDS' + }, + max_expire_seconds: { + format: Number, + default: 86400 * 7, + env: 'MAX_EXPIRE_SECONDS' + }, + download_counts: { + format: 'positive-int-array', + default: [1, 2, 3, 4, 5, 20, 50, 100], + env: 'DOWNLOAD_COUNTS' + }, + default_downloads: { + format: Number, + default: 1, + env: 'DEFAULT_DOWNLOADS' + }, + max_downloads: { + format: Number, + default: 100, + env: 'MAX_DOWNLOADS' + }, + max_files_per_archive: { + format: Number, + default: 64, + env: 'MAX_FILES_PER_ARCHIVE' + }, + max_archives_per_user: { + format: Number, + default: 16, + env: 'MAX_ARCHIVES_PER_USER' + }, + redis_host: { + format: String, + default: 'localhost', + env: 'REDIS_HOST' + }, + redis_port: { + format: Number, + default: 6379, + env: 'REDIS_PORT' + }, + redis_user: { + format: String, + default: '', + env: 'REDIS_USER' + }, + redis_password: { + format: String, + default: '', + env: 'REDIS_PASSWORD' + }, + redis_db: { + format: String, + default: '', + env: 'REDIS_DB' + }, + redis_event_expire: { + format: Boolean, + default: false, + env: 'REDIS_EVENT_EXPIRE' + }, + redis_retry_time: { + format: Number, + default: 10000, + env: 'REDIS_RETRY_TIME' + }, + redis_retry_delay: { + format: Number, + default: 500, + env: 'REDIS_RETRY_DELAY' + }, + listen_address: { + format: 'ipaddress', + default: '0.0.0.0', + env: 'IP_ADDRESS' + }, + listen_port: { + format: 'port', + default: __PORT__, + arg: 'port', + env: 'PORT' + }, + sentry_id: { + format: String, + default: '', + env: 'SENTRY_CLIENT' + }, + sentry_dsn: { + format: String, + default: '', + env: 'SENTRY_DSN' + }, + env: { + format: ['production', 'development', 'test'], + default: 'development', + env: 'NODE_ENV' + }, + max_file_size: { + format: Number, + default: 1024 * 1024 * 1024 * 2.5, + env: 'MAX_FILE_SIZE' + }, + l10n_dev: { + format: Boolean, + default: false, + env: 'L10N_DEV' + }, + base_url: { + format: 'url', + default: 'https://__DOMAIN__', + env: 'BASE_URL' + }, + detect_base_url: { + format: Boolean, + default: false, + env: 'DETECT_BASE_URL' + }, + file_dir: { + format: 'String', + default: `${tmpdir()}${path.sep}send-${randomBytes(4).toString('hex')}`, + env: 'FILE_DIR' + }, + fxa_url: { + format: 'url', + default: 'https://send-fxa.dev.lcip.org', + env: 'FXA_URL' + }, + fxa_client_id: { + format: String, + default: '', // disabled + env: 'FXA_CLIENT_ID' + }, + fxa_key_scope: { + format: String, + default: 'https://identity.mozilla.com/apps/send', + env: 'FXA_KEY_SCOPE' + }, + fxa_csp_oauth_url: { + format: String, + default: '', + env: 'FXA_CSP_OAUTH_URL' + }, + fxa_csp_content_url: { + format: String, + default: '', + env: 'FXA_CSP_CONTENT_URL' + }, + fxa_csp_profile_url: { + format: String, + default: '', + env: 'FXA_CSP_PROFILE_URL' + }, + fxa_csp_profileimage_url: { + format: String, + default: '', + env: 'FXA_CSP_PROFILEIMAGE_URL' + }, + survey_url: { + format: String, + default: '', + env: 'SURVEY_URL' + }, + ip_db: { + format: String, + default: '', + env: 'IP_DB' + }, + footer_donate_url: { + format: String, + default: '', + env: 'SEND_FOOTER_DONATE_URL' + }, + footer_cli_url: { + format: String, + default: 'https://github.com/timvisee/ffsend', + env: 'SEND_FOOTER_CLI_URL' + }, + footer_dmca_url: { + format: String, + default: '', + env: 'SEND_FOOTER_DMCA_URL' + }, + footer_source_url: { + format: String, + default: 'https://github.com/timvisee/send', + env: 'SEND_FOOTER_SOURCE_URL' + } +}); + +// Perform validation +conf.validate({ allowed: 'strict' }); + +const props = conf.getProperties(); + +const deriveBaseUrl = req => { + if (!props.detect_base_url) { + return props.base_url; + } + + const protocol = req.secure ? 'https://' : 'http://'; + return `${protocol}${req.headers.host}`; +}; + +module.exports = { + ...props, + deriveBaseUrl +}; diff --git a/conf/nginx.conf b/conf/nginx.conf new file mode 100644 index 0000000..2c8ef20 --- /dev/null +++ b/conf/nginx.conf @@ -0,0 +1,26 @@ +location / { + + proxy_pass http://127.0.0.1:__PORT__; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $server_name; + + proxy_http_version 1.1; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; +} + +location /api/ws { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Connection ""; + proxy_connect_timeout 4000s; + proxy_read_timeout 4000s; + proxy_pass http://127.0.0.1:__PORT__; +} diff --git a/conf/systemd.service b/conf/systemd.service new file mode 100644 index 0000000..76be492 --- /dev/null +++ b/conf/systemd.service @@ -0,0 +1,16 @@ +[Unit] +Description=Send: private file sharing +After=syslog.target network.target redis-server.service + +[Service] +Type=simple +User=__APP__ +Group=__APP__ +WorkingDirectory=__FINALPATH__ +Environment="NODE_ENV=production" +#Environment="__YNH_NODE_LOAD_PATH__" +ExecStart=__YNH_NODE__ __FINALPATH__/server/bin/prod.js +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/doc/.DS_Store b/doc/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..89d6be550c959cabe5cee10f79099a460aff7eae GIT binary patch literal 6148 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�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�JFv415E@iDMf{4ILaNB=wz@IU6Nz*+fk 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

= 4.2.4" + }, + "multi_instance": true, + "services": [ + "nginx" + ], + "arguments": { + "install" : [ + { + "name": "domain", + "type": "domain", + "example": "example.com" + }, + { + "name": "is_public", + "type": "boolean", + "help": { + "en": "If enabled, Send will be accessible by people who do not have an account. This can be changed later via the webadmin.", + "fr": "Si cette case est cochée, Send sera accessible aux personnes n’ayant pas de compte. Vous pourrez changer ceci plus tard via la webadmin." + }, + "default": true + } + ] + } +} diff --git a/scripts/_common.sh b/scripts/_common.sh new file mode 100644 index 0000000..247f831 --- /dev/null +++ b/scripts/_common.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +#================================================= +# COMMON VARIABLES +#================================================= + +# dependencies used by the app +#pkg_dependencies="redis-server" + +nodejs_version=15 + +# dependencies used by the app +#pkg_dependencies="redis-server" + + +#================================================= +# PERSONAL HELPERS +#================================================= + +#================================================= +# EXPERIMENTAL HELPERS +#================================================= + +#================================================= +# FUTURE OFFICIAL HELPERS +#================================================= diff --git a/scripts/backup b/scripts/backup new file mode 100644 index 0000000..d548f15 --- /dev/null +++ b/scripts/backup @@ -0,0 +1,61 @@ +#!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source ../settings/scripts/_common.sh +source /usr/share/yunohost/helpers + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + ynh_clean_check_starting +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_print_info --message="Loading installation settings..." + +app=$YNH_APP_INSTANCE_NAME + +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) + +#================================================= +# DECLARE DATA AND CONF FILES TO BACKUP +#================================================= +ynh_print_info --message="Declaring files to be backed up..." + +#================================================= +# BACKUP THE APP MAIN DIR +#================================================= + +ynh_backup --src_path="$final_path" + +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= + +ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# SPECIFIC BACKUP +#================================================= +# BACKUP SYSTEMD +#================================================= + +ynh_backup --src_path="/etc/systemd/system/$app.service" + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." diff --git a/scripts/change_url b/scripts/change_url new file mode 100644 index 0000000..8607037 --- /dev/null +++ b/scripts/change_url @@ -0,0 +1,135 @@ +#!/bin/bash + +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# RETRIEVE ARGUMENTS +#================================================= + +old_domain=$YNH_APP_OLD_DOMAIN +old_path=$YNH_APP_OLD_PATH + +new_domain=$YNH_APP_NEW_DOMAIN +new_path="/" + +app=$YNH_APP_INSTANCE_NAME + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 + +# Needed for helper "ynh_add_nginx_config" +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +port=$(ynh_app_setting_get --app=$app --key=port) + +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up $app before changing its URL (may take a while)..." --weight=1 + +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + # Remove the new domain config file, the remove script won't do it as it doesn't know yet its location. + ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" + + # restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# CHECK WHICH PARTS SHOULD BE CHANGED +#================================================= + +change_domain=0 +if [ "$old_domain" != "$new_domain" ] +then + change_domain=1 +fi + +change_path=0 +if [ "$old_path" != "$new_path" ] +then + change_path=1 +fi + +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." --weight=1 + +ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" + +#================================================= +# MODIFY URL IN NGINX CONF +#================================================= +ynh_script_progression --message="Updating NGINX web server configuration..." --weight=1 + +nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf + +# Change the path in the NGINX config file +if [ $change_path -eq 1 ] +then + # Make a backup of the original NGINX config file if modified + ynh_backup_if_checksum_is_different --file="$nginx_conf_path" + # Set global variables for NGINX helper + domain="$old_domain" + path_url="$new_path" + # Create a dedicated NGINX config + ynh_add_nginx_config +fi + +# Change the domain for NGINX +if [ $change_domain -eq 1 ] +then + # Delete file checksum for the old conf file location + ynh_delete_file_checksum --file="$nginx_conf_path" + mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf + # Store file checksum for the new config file location + ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" +fi + +#================================================= +# ADD A CONFIGURATION +#================================================= +ynh_script_progression --message="Adding a configuration file..." --weight=2 + +ynh_add_config --template="../conf/config.js" --destination="$final_path/server/config.js" + +chmod 400 "$final_path/server/config.js" +chown $app:$app "$final_path/server/config.js" + +#================================================= +# GENERIC FINALISATION +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --weight=1 + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="systemd" #--line_match="HTTP Server listening" + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Change of URL completed for $app" --last diff --git a/scripts/install b/scripts/install new file mode 100644 index 0000000..261a9f7 --- /dev/null +++ b/scripts/install @@ -0,0 +1,171 @@ +#!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + ynh_clean_check_starting +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# RETRIEVE ARGUMENTS FROM THE MANIFEST +#================================================= + +domain=$YNH_APP_ARG_DOMAIN +path_url="/" +is_public=$YNH_APP_ARG_IS_PUBLIC + +app=$YNH_APP_INSTANCE_NAME + +#================================================= +# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS +#================================================= +ynh_script_progression --message="Validating installation parameters..." --weight=1 + +final_path=/var/www/$app +test ! -e "$final_path" || ynh_die --message="This path already contains a folder" + +# Register (book) web path +ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url + +#================================================= +# STORE SETTINGS FROM MANIFEST +#================================================= +ynh_script_progression --message="Storing installation settings..." --weight=2 + +ynh_app_setting_set --app=$app --key=domain --value=$domain +ynh_app_setting_set --app=$app --key=path --value=$path_url + +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# FIND AND OPEN A PORT +#================================================= +ynh_script_progression --message="Configuring firewall..." --weight=2 + +# Find an available port +port=$(ynh_find_port --port=1443) +ynh_app_setting_set --app=$app --key=port --value=$port + +#================================================= +# INSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Installing dependencies..." --weight=20 + +#ynh_install_app_dependencies $pkg_dependencies + +# Install Nodejs +ynh_exec_warn_less ynh_install_nodejs --nodejs_version=$nodejs_version + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Configuring system user..." --weight=3 + +# Create a system user +ynh_system_user_create --username=$app --home_dir=$final_path + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= +ynh_script_progression --message="Setting up source files..." --weight=2 + +ynh_app_setting_set --app=$app --key=final_path --value=$final_path +# Download, check integrity, uncompress and patch the source from app.src +ynh_setup_source --dest_dir=$final_path + +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" +chmod +x "$final_path/server/bin/prod.js" + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Configuring NGINX web server..." --weight=2 + +ynh_replace_string --match_string="__ENV_PATH__" --replace_string="$PATH" --target_file="../conf/systemd.service" + +# Create a dedicated NGINX config +ynh_add_nginx_config + +#================================================= +# ADD A CONFIGURATION +#================================================= +ynh_script_progression --message="Adding a configuration file..." --weight=2 + +ynh_add_config --template="../conf/config.js" --destination="$final_path/server/config.js" + +chmod 400 "$final_path/server/config.js" +chown $app:$app "$final_path/server/config.js" + +#================================================= +# SPECIFIC SETUP +#============================================== +# INSTALL HEDGEDOC +#============================================== +ynh_script_progression --message="Building $app... (this will take some time and resources!)" --weight=20 + +pushd "$final_path" + ynh_use_nodejs + ynh_exec_warn_less ynh_exec_as $app npm install + ynh_exec_warn_less ynh_exec_as $app npm run build +popd + +#================================================= +# SETUP SYSTEMD +#================================================= +ynh_script_progression --message="Configuring a systemd service..." --weight=1 + +ynh_add_systemd_config + +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." + +yunohost service add $app --description="Simple, private file sharing" --log="/var/log/$app/$app.log" + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --weight=2 + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="systemd" #--line_match="HTTP Server listening" + +#================================================= +# SETUP SSOWAT +#================================================= +ynh_script_progression --message="Configuring permissions..." --weight=1 + +# Make app public if necessary or protect it +if [ $is_public -eq 1 ] +then + ynh_permission_update --permission "main" --add "visitors" +fi + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=2 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Installation of $app completed" --last diff --git a/scripts/remove b/scripts/remove new file mode 100644 index 0000000..dc4d988 --- /dev/null +++ b/scripts/remove @@ -0,0 +1,84 @@ +#!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 + +app=$YNH_APP_INSTANCE_NAME + +domain=$(ynh_app_setting_get --app=$app --key=domain) +port=$(ynh_app_setting_get --app=$app --key=port) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) + +#================================================= +# STANDARD REMOVE +#================================================= +# REMOVE SERVICE INTEGRATION IN YUNOHOST +#================================================= + +# Remove the service from the list of services known by Yunohost (added from `yunohost service add`) +if ynh_exec_warn_less yunohost service status $app >/dev/null +then + ynh_script_progression --message="Removing $app service..." --weight=1 + yunohost service remove $app +fi + +#================================================= +# STOP AND REMOVE SERVICE +#================================================= +ynh_script_progression --message="Stopping and removing the systemd service..." --weight=1 + +# Remove the dedicated systemd config +ynh_remove_systemd_config + +#================================================= +# REMOVE DEPENDENCIES +#================================================= +ynh_script_progression --message="Removing dependencies..." --weight=1 + +# Remove metapackage and its dependencies +#ynh_remove_app_dependencies + +ynh_remove_nodejs + +#================================================= +# REMOVE APP MAIN DIR +#================================================= +ynh_script_progression --message="Removing $app main directory..." --weight=6 + +# Remove the app directory securely +ynh_secure_remove --file="$final_path" + +#================================================= +# REMOVE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Removing NGINX web server configuration..." --weight=5 + +# Remove the dedicated nginx config +ynh_remove_nginx_config + +#================================================= +# GENERIC FINALIZATION +#================================================= +# REMOVE DEDICATED USER +#================================================= +ynh_script_progression --message="Removing the dedicated system user..." --weight=1 + +# Delete a system user +ynh_system_user_delete --username=$app + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Removal of $app completed" --last diff --git a/scripts/restore b/scripts/restore new file mode 100644 index 0000000..f72b8d3 --- /dev/null +++ b/scripts/restore @@ -0,0 +1,120 @@ +#!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source ../settings/scripts/_common.sh +source /usr/share/yunohost/helpers + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + ynh_clean_check_starting +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading settings..." --weight=1 + +app=$YNH_APP_INSTANCE_NAME + +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) + +#================================================= +# CHECK IF THE APP CAN BE RESTORED +#================================================= +ynh_script_progression --message="Validating restoration parameters..." --weight=2 + +ynh_webpath_available --domain=$domain --path_url=$path_url \ + || ynh_die --message="Path not available: ${domain}${path_url}" +test ! -d $final_path \ + || ynh_die --message="There is already a directory: $final_path " + +#================================================= +# STANDARD RESTORATION STEPS +#================================================= +# RESTORE THE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Restoring the NGINX configuration..." + +ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# RECREATE THE DEDICATED USER +#================================================= +ynh_script_progression --message="Recreating the dedicated system user..." --weight=1 + +# Create the dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir="$final_path" + +#================================================= +# RESTORE THE APP MAIN DIR +#================================================= +ynh_script_progression --message="Restoring the app main directory..." --weight=6 + +ynh_restore_file --origin_path="$final_path" + +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" +chmod +x "$final_path/server/bin/prod.js" + +#================================================= +# SPECIFIC RESTORATION +#================================================= +# REINSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Reinstalling dependencies..." --weight=7 + +# Define and install dependencies +#ynh_install_app_dependencies $pkg_dependencies + +# Install Nodejs +ynh_exec_warn_less ynh_install_nodejs --nodejs_version=$nodejs_version + +#================================================= +# RESTORE SYSTEMD +#================================================= +ynh_script_progression --message="Restoring the systemd configuration..." --weight=5 + +ynh_restore_file --origin_path="/etc/systemd/system/$app.service" +systemctl enable $app.service --quiet + +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." + +yunohost service add $app --description="Simple, private file sharing" --log="/var/log/$app/$app.log" + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --log_path="systemd" #--line_match="HTTP Server listening" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Restoration completed for $app" --last diff --git a/scripts/upgrade b/scripts/upgrade new file mode 100644 index 0000000..dce76da --- /dev/null +++ b/scripts/upgrade @@ -0,0 +1,165 @@ +#!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=2 + +app=$YNH_APP_INSTANCE_NAME + +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +is_public=$(ynh_app_setting_get --app=$app --key=is_public) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +port=$(ynh_app_setting_get --app=$app --key=port) + +#================================================= +# CHECK VERSION +#================================================= +ynh_script_progression --message="Checking version..." + +upgrade_type=$(ynh_check_app_version_changed) + +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up $app before upgrading (may take a while)..." --weight=10 + +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + # restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# STANDARD UPGRADE STEPS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." --weight=1 + +ynh_systemd_action --service_name=$app --action="stop" --log_path="systemd" + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Making sure dedicated system user exists..." --weight=1 + +# Create a dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir="$final_path" + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= + +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Upgrading source files..." --weight=10 + + # Create a temporary directory + tmpdir="$(mktemp -d)" + + # Backup the config file in the temp dir + cp -a "$final_path/server/config.js" "$tmpdir/config.js" + + # Remove the app directory securely + ynh_secure_remove --file=$final_path + + # Download, check integrity, uncompress and patch the source from app.src + ynh_setup_source --dest_dir=$final_path + + #Copy the admin saved settings from tmp directory to final path + cp -a "$tmpdir/config.js" "$final_path/server/config.js" + + # Remove the tmp directory securely + ynh_secure_remove --file="$tmpdir" +fi + +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" +chmod +x "$final_path/server/bin/prod.js" + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Upgrading NGINX web server configuration..." --weight=2 + +# Create a dedicated NGINX config +ynh_add_nginx_config + +#================================================= +# UPGRADE DEPENDENCIES +#================================================= +ynh_script_progression --message="Upgrading dependencies..." --weight=18 + +#ynh_install_app_dependencies $pkg_dependencies + +# Install Nodejs +ynh_exec_warn_less ynh_install_nodejs --nodejs_version=$nodejs_version + +#================================================= +# SPECIFIC UPGRADE +#================================================ +# INSTALL SEND +#================================================ + +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Building $app... (this will take some time and resources!)" --weight=16 + + pushd "$final_path" + ynh_use_nodejs + ynh_exec_warn_less ynh_exec_as $app npm install + ynh_exec_warn_less ynh_exec_as $app npm run build + popd +fi + +#================================================= +# SETUP SYSTEMD +#================================================= +ynh_script_progression --message="Configuring a systemd service..." --weight=2 + +ynh_replace_string --match_string="__ENV_PATH__" --replace_string="$PATH" --target_file="../conf/systemd.service" + +# Create a dedicated systemd config +ynh_add_systemd_config + +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." + +yunohost service add $app --description="Simple, private file sharing" --log="/var/log/$app/$app.log" + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --log_path="systemd" #--line_match="HTTP Server listening" + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Upgrade of $app completed" --last