Fork the GNU Taler sources
This commit is contained in:
parent
ed877a4f93
commit
36e102131a
|
@ -0,0 +1,661 @@
|
|||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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/>.
|
||||
|
||||
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
|
||||
<http://www.gnu.org/licenses/>.
|
|
@ -0,0 +1,21 @@
|
|||
Sun 08 Aug 2021 08:44:35 PM CEST
|
||||
Releasing taler-bank 0.8.2. -CG
|
||||
|
||||
Tue Apr 10 02:39:19 CEST 2018
|
||||
Releasing taler-bank-0.5.1 -FD
|
||||
|
||||
Tue Feb 13 10:05:06 CET 2018
|
||||
Introducing the /reject REST API, internal wire
|
||||
transfers between users, and a middleware-based
|
||||
exceptions management.
|
||||
|
||||
Thu Jul 13 11:43:05 CEST 2017
|
||||
Testing against ill-formed config file
|
||||
|
||||
Tue Jun 6 14:39:45 CEST 2017
|
||||
Implementing /history API where any authenticated user
|
||||
can check his financial situation. Removing the "admin"
|
||||
interface. Implementing debt limiting. -MS
|
||||
|
||||
Wed Jun 1 17:27:36 CEST 2016
|
||||
Releasing taler-bank-0.0.0. -CG
|
|
@ -0,0 +1,368 @@
|
|||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. This file is offered as-is,
|
||||
without warranty of any kind.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell command './configure && make && make install'
|
||||
should configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the 'README' file for
|
||||
instructions specific to this package. Some packages provide this
|
||||
'INSTALL' file but do not implement all of the features documented
|
||||
below. The lack of an optional feature in a given package is not
|
||||
necessarily a bug. More recommendations for GNU packages can be found
|
||||
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||
|
||||
The 'configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a 'Makefile' in each directory of the package.
|
||||
It may also create one or more '.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script 'config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file 'config.log' containing compiler output (useful mainly for
|
||||
debugging 'configure').
|
||||
|
||||
It can also use an optional file (typically called 'config.cache' and
|
||||
enabled with '--cache-file=config.cache' or simply '-C') that saves the
|
||||
results of its tests to speed up reconfiguring. Caching is disabled by
|
||||
default to prevent problems with accidental use of stale cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how 'configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the 'README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point 'config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file 'configure.ac' (or 'configure.in') is used to create
|
||||
'configure' by a program called 'autoconf'. You need 'configure.ac' if
|
||||
you want to change it or regenerate 'configure' using a newer version of
|
||||
'autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. 'cd' to the directory containing the package's source code and type
|
||||
'./configure' to configure the package for your system.
|
||||
|
||||
Running 'configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type 'make' to compile the package.
|
||||
|
||||
3. Optionally, type 'make check' to run any self-tests that come with
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type 'make install' to install the programs and any data files and
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the 'make install' phase executed with root
|
||||
privileges.
|
||||
|
||||
5. Optionally, type 'make installcheck' to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior 'make install' required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
6. You can remove the program binaries and object files from the
|
||||
source code directory by typing 'make clean'. To also remove the
|
||||
files that 'configure' created (so you can compile the package for
|
||||
a different kind of computer), type 'make distclean'. There is
|
||||
also a 'make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
7. Often, you can also type 'make uninstall' to remove the installed
|
||||
files again. In practice, not all packages have tested that
|
||||
uninstallation works correctly, even though it is required by the
|
||||
GNU Coding Standards.
|
||||
|
||||
8. Some packages, particularly those that use Automake, provide 'make
|
||||
distcheck', which can by used by developers to test that all other
|
||||
targets like 'make install' and 'make uninstall' work correctly.
|
||||
This target is generally not run by end users.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the 'configure' script does not know about. Run './configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give 'configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here is
|
||||
an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU 'make'. 'cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the 'configure' script. 'configure' automatically checks for the source
|
||||
code in the directory that 'configure' is in and in '..'. This is known
|
||||
as a "VPATH" build.
|
||||
|
||||
With a non-GNU 'make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use 'make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
On MacOS X 10.5 and later systems, you can create libraries and
|
||||
executables that work on multiple system types--known as "fat" or
|
||||
"universal" binaries--by specifying multiple '-arch' options to the
|
||||
compiler but only a single '-arch' option to the preprocessor. Like
|
||||
this:
|
||||
|
||||
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CPP="gcc -E" CXXCPP="g++ -E"
|
||||
|
||||
This is not guaranteed to produce working output in all cases, you
|
||||
may have to build one architecture at a time and combine the results
|
||||
using the 'lipo' tool if you have problems.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, 'make install' installs the package's commands under
|
||||
'/usr/local/bin', include files under '/usr/local/include', etc. You
|
||||
can specify an installation prefix other than '/usr/local' by giving
|
||||
'configure' the option '--prefix=PREFIX', where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like '--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run 'configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them. In general, the default
|
||||
for these options is expressed in terms of '${prefix}', so that
|
||||
specifying just '--prefix' will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to 'configure'; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
'make install' command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, 'make install
|
||||
prefix=/alternate/directory' will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
'${prefix}'. Any directories that were specified during 'configure',
|
||||
but not in terms of '${prefix}', must each be overridden at install time
|
||||
for the entire installation to be relocated. The approach of makefile
|
||||
variable overrides for each directory variable is required by the GNU
|
||||
Coding Standards, and ideally causes no recompilation. However, some
|
||||
platforms have known limitations with the semantics of shared libraries
|
||||
that end up requiring recompilation when using this method, particularly
|
||||
noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the 'DESTDIR' variable. For
|
||||
example, 'make install DESTDIR=/alternate/directory' will prepend
|
||||
'/alternate/directory' before all installation names. The approach of
|
||||
'DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of '${prefix}'
|
||||
at 'configure' time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving 'configure' the
|
||||
option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
|
||||
|
||||
Some packages pay attention to '--enable-FEATURE' options to
|
||||
'configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to '--with-PACKAGE' options, where PACKAGE
|
||||
is something like 'gnu-as' or 'x' (for the X Window System). The
|
||||
'README' should mention any '--enable-' and '--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, 'configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the 'configure' options '--x-includes=DIR' and
|
||||
'--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of 'make' will be. For these packages, running './configure
|
||||
--enable-silent-rules' sets the default to minimal output, which can be
|
||||
overridden with 'make V=1'; while running './configure
|
||||
--disable-silent-rules' sets the default to verbose, which can be
|
||||
overridden with 'make V=0'.
|
||||
|
||||
Particular systems
|
||||
==================
|
||||
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
|
||||
is not installed, it is recommended to use the following options in
|
||||
order to use an ANSI C compiler:
|
||||
|
||||
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX 'make' updates targets which have the same time stamps as their
|
||||
prerequisites, which makes it generally unusable when shipped generated
|
||||
files such as 'configure' are involved. Use GNU 'make' instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
|
||||
workaround. If GNU CC is not installed, it is therefore recommended to
|
||||
try
|
||||
|
||||
./configure CC="cc"
|
||||
|
||||
and if that doesn't work, try
|
||||
|
||||
./configure CC="cc -nodtk"
|
||||
|
||||
On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
|
||||
directory contains several dysfunctional programs; working variants of
|
||||
these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
|
||||
in your 'PATH', put it _after_ '/usr/bin'.
|
||||
|
||||
On Haiku, software installed for all users goes in '/boot/common',
|
||||
not '/usr/local'. It is recommended to use the following options:
|
||||
|
||||
./configure --prefix=/boot/common
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features 'configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, 'configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
'--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as 'sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS
|
||||
KERNEL-OS
|
||||
|
||||
See the file 'config.sub' for the possible values of each field. If
|
||||
'config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option '--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with '--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for 'configure' scripts to share,
|
||||
you can create a site shell script called 'config.site' that gives
|
||||
default values for variables like 'CC', 'cache_file', and 'prefix'.
|
||||
'configure' looks for 'PREFIX/share/config.site' if it exists, then
|
||||
'PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
'CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all 'configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to 'configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the 'configure' command line, using 'VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified 'gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
|
||||
Autoconf limitation. Until the limitation is lifted, you can use this
|
||||
workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
'configure' Invocation
|
||||
======================
|
||||
|
||||
'configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
'--help'
|
||||
'-h'
|
||||
Print a summary of all of the options to 'configure', and exit.
|
||||
|
||||
'--help=short'
|
||||
'--help=recursive'
|
||||
Print a summary of the options unique to this package's
|
||||
'configure', and exit. The 'short' variant lists options used only
|
||||
in the top level, while the 'recursive' variant lists options also
|
||||
present in any nested packages.
|
||||
|
||||
'--version'
|
||||
'-V'
|
||||
Print the version of Autoconf used to generate the 'configure'
|
||||
script, and exit.
|
||||
|
||||
'--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally 'config.cache'. FILE defaults to '/dev/null' to
|
||||
disable caching.
|
||||
|
||||
'--config-cache'
|
||||
'-C'
|
||||
Alias for '--cache-file=config.cache'.
|
||||
|
||||
'--quiet'
|
||||
'--silent'
|
||||
'-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to '/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
'--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
'configure' can determine that directory automatically.
|
||||
|
||||
'--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names:: for
|
||||
more details, including other options available for fine-tuning the
|
||||
installation locations.
|
||||
|
||||
'--no-create'
|
||||
'-n'
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
'configure' also accepts some other, not widely useful, options. Run
|
||||
'configure --help' for more details.
|
122
README.md
122
README.md
|
@ -1,3 +1,121 @@
|
|||
# bank
|
||||
# GNU Taler Demo Bank
|
||||
|
||||
The base bank repository, based on GNU Taler
|
||||
This code implements a bank Web portal that tightly integrates
|
||||
with the GNU Taler payment system. The bank it primarily meant
|
||||
be used as part of a demonstrator for the Taler system, but
|
||||
can also be used in standalone deployments for a regional/local
|
||||
currency.
|
||||
|
||||
## Deprecation Notice
|
||||
|
||||
This project is being replaced with https://git.taler.net/libeufin.git
|
||||
No more feature will be worked in this project so hack at your own risk.
|
||||
|
||||
## Installation
|
||||
|
||||
### PyPI
|
||||
|
||||
To install the bank without building it from source, run
|
||||
```
|
||||
$ pip3 install --user talerbank
|
||||
```
|
||||
to get the latest version published in the Python Package Index (PyPI).
|
||||
|
||||
|
||||
### Prerequisites
|
||||
|
||||
To build the bank, you need:
|
||||
* ``python>=3.8``
|
||||
* ``pip3``
|
||||
* ``poetry``
|
||||
* Either install with ``pip3 install --user poetry``, your distribution's package manager,
|
||||
or as recommended in the [poetry documentation](https://python-poetry.org/docs/#installation).
|
||||
|
||||
|
||||
### GNU-Style Installation
|
||||
|
||||
If you are building from the git repository, first run ``./boostrap``.
|
||||
|
||||
Then run
|
||||
```
|
||||
$ ./configure
|
||||
$ make install
|
||||
```
|
||||
to install the bank for the current user.
|
||||
|
||||
|
||||
### Custom Installation
|
||||
|
||||
To install with custom options, first build the wheel for the bank
|
||||
and then install via ``pip3``:
|
||||
```
|
||||
$ ./configure
|
||||
$ make wheel
|
||||
$ pip3 $CUSTOM_OPTIONS ./dist/talerbank-$VERSION-py3-none-any.whl
|
||||
```
|
||||
|
||||
|
||||
## Internationalization
|
||||
|
||||
After new strings to translate enter the bank's text, run the
|
||||
following command in order to expand the current PO files:
|
||||
|
||||
```
|
||||
$ make i18n-strings
|
||||
```
|
||||
|
||||
It is then required to put the extended PO files under versioning.
|
||||
|
||||
The following command creates *new* languages to be translated. In
|
||||
particular, it produces the PO file for the language being added.
|
||||
|
||||
```
|
||||
$ python3 manage.py makemessages -l $LANG
|
||||
```
|
||||
|
||||
However, you should probably use https://weblate.taler.net/ to add
|
||||
new languages instead.
|
||||
|
||||
|
||||
## Configuring the Bank
|
||||
|
||||
The bank obeys to the INI syntax for configuration files.
|
||||
When launched, the bank will by default look for a configuration
|
||||
file located at ~/.config/taler.conf. To override this behaviour,
|
||||
give the -c option when launching the bank.
|
||||
|
||||
The following configuration instance makes the bank serve over
|
||||
HTTP, at port 5882.
|
||||
|
||||
```
|
||||
[taler]
|
||||
currency = LOCALKUDOS
|
||||
|
||||
[bank]
|
||||
serve = http
|
||||
http_port = 5882
|
||||
database = postgres:///talerlocal
|
||||
max_debt = LOCALKUDOS:500.0
|
||||
max_debt_bank = LOCALKUDOS:1000000000.0
|
||||
allow_registrations = YES
|
||||
base_url = http://localhost:5882/
|
||||
suggested_exchange = http://localhost:5884/
|
||||
```
|
||||
|
||||
|
||||
## Launching the Bank
|
||||
|
||||
```
|
||||
$ taler-bank-manage serve
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
From the repository's top directory:
|
||||
|
||||
$ make check
|
||||
|
||||
|
||||
## How to Force Migrations
|
||||
|
||||
https://simpleisbetterthancomplex.com/tutorial/2016/07/26/how-to-reset-migrations.html
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
[bank]
|
||||
|
||||
# Which database should we use?
|
||||
DATABASE = postgres:///talerbank
|
||||
|
||||
# FIXME
|
||||
MAX_DEBT = KUDOS:50.0
|
||||
|
||||
# FIXME
|
||||
MAX_DEBT_BANK = KUDOS:0.0
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Bootstrap the repository. Used when the repository is checked out from git.
|
||||
# When using the source tarball, running this script is not necessary.
|
||||
|
||||
set -eu
|
||||
|
||||
# Skip git-commands when installing from a TGZ package.
|
||||
if [ -d .git ] ; then
|
||||
if ! git --version >/dev/null; then
|
||||
echo "git not installed"
|
||||
exit 1
|
||||
fi
|
||||
git submodule sync
|
||||
git submodule update --init
|
||||
fi
|
||||
|
||||
rm -f ./configure
|
||||
cp build-system/taler-build-scripts/configure ./configure
|
|
@ -0,0 +1,60 @@
|
|||
# This Makefile is in the public domain
|
||||
|
||||
version := $(shell poetry version | awk '{ print $$2 }')
|
||||
|
||||
.PHONY: all
|
||||
all: wheel
|
||||
|
||||
.PHONY: poetry-install
|
||||
poetry-install:
|
||||
poetry install
|
||||
|
||||
.PHONY: wheel
|
||||
wheel: poetry-install
|
||||
poetry run python3 manage.py compilemessages
|
||||
poetry build -f wheel
|
||||
|
||||
.PHONY: install
|
||||
install: wheel
|
||||
pip3 install --upgrade --ignore-installed --user "dist/talerbank-$(version)-py3-none-any.whl"
|
||||
|
||||
|
||||
.PHONY: uninstall
|
||||
uninstall:
|
||||
pip3 uninstall talerbank
|
||||
|
||||
.PHONY: i18n-strings
|
||||
i18n-strings: poetry-install
|
||||
poetry run python3 manage.py makemessages -l it
|
||||
poetry run python3 manage.py makemessages -l de
|
||||
# Also update template for new languages
|
||||
poetry run python3 manage.py makemessages -l en
|
||||
mv talerbank/app/locale/en/LC_MESSAGES/django.po talerbank/app/locale/django.pot
|
||||
rm -r talerbank/app/locale/en/
|
||||
|
||||
# See bug #5850 for some test cases that are currently disabled.
|
||||
.PHONY: check
|
||||
check: poetry-install
|
||||
poetry run ./run-tests.sh
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf dist
|
||||
|
||||
|
||||
configure: build-system/taler-build-scripts/
|
||||
./bootstrap
|
||||
|
||||
.PHONY: dist
|
||||
dist: configure
|
||||
./build-system/taler-build-scripts/archive-with-submodules/git_archive_all.py --include ./bootstrap --include ./configure taler-bank-$(version).tar.gz
|
||||
|
||||
.PHONY: pretty
|
||||
pretty: poetry-install
|
||||
poetry run black talerbank/
|
||||
|
||||
Makefile: build-system/Makefile configure
|
||||
@echo updating makefile
|
||||
cp build-system/Makefile .
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# This configure.py file is places in the public domain.
|
||||
|
||||
# Configure the build directory.
|
||||
# This file is invoked by './configure' and should usually not be invoked
|
||||
# manually.
|
||||
|
||||
import talerbuildconfig as tbc
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
if getattr(tbc, "serialversion", 0) < 2:
|
||||
print("talerbuildconfig outdated, please update the build-common submodule and/or bootstrap")
|
||||
sys.exit(1)
|
||||
|
||||
b = tbc.BuildConfig()
|
||||
|
||||
# Declare dependencies
|
||||
b.add_tool(tbc.PosixTool("find"))
|
||||
b.add_tool(tbc.PosixTool("awk"))
|
||||
b.add_tool(tbc.GenericTool("pip3", version_arg="--version"))
|
||||
b.add_tool(tbc.GenericTool("poetry", version_arg="-V"))
|
||||
|
||||
b.run()
|
||||
|
||||
print("copying Makefile")
|
||||
shutil.copyfile("build-system/Makefile", "Makefile")
|
|
@ -0,0 +1,331 @@
|
|||
# Doxyfile 1.8.13
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "taler-demobank"
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = doxygen-doc/
|
||||
CREATE_SUBDIRS = yes
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
"The $name widget" \
|
||||
"The $name file" \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES =
|
||||
TCL_SUBST =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING = in=Python
|
||||
MARKDOWN_SUPPORT = YES
|
||||
TOC_INCLUDE_HEADINGS = 0
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
GROUP_NESTED_COMPOUNDS = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
HIDE_COMPOUND_REFERENCE= NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTORS_1ST = NO
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = NO
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_AS_ERROR = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT =
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.py *.in
|
||||
RECURSIVE = YES
|
||||
EXCLUDE = Makefile.in
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
CLANG_OPTIONS =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = NO
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
CHM_INDEX_ENCODING =
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = org.doxygen.Project
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
MATHJAX_EXTENSIONS =
|
||||
MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = YES
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
LATEX_FOOTER =
|
||||
LATEX_EXTRA_STYLESHEET =
|
||||
LATEX_EXTRA_FILES =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
LATEX_TIMESTAMP = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_SOURCE_CODE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_SUBDIR =
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = NO
|
||||
MSCGEN_PATH =
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
PLANTUML_JAR_PATH =
|
||||
PLANTUML_CFG_FILE =
|
||||
PLANTUML_INCLUDE_PATH =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
|
@ -0,0 +1,35 @@
|
|||
#!/bin/bash
|
||||
# This file is in the public domain
|
||||
# Launch uwsgi: i.e. connects django to nginx
|
||||
|
||||
print_usage () {
|
||||
echo Usage ./django_wsgi.sh virtualenv_dir/
|
||||
exit
|
||||
}
|
||||
|
||||
PROJ_DIR=""
|
||||
ENV_DIR=""
|
||||
|
||||
#if test -d "$1";
|
||||
# then PROJ_DIR=$1
|
||||
#else echo "Please give a valid project directory"
|
||||
# print_usage
|
||||
#fi
|
||||
|
||||
if test -d "$1";
|
||||
then ENV_DIR=$1
|
||||
else echo "Please give a valid virtualenv's directory"
|
||||
print_usage
|
||||
fi
|
||||
|
||||
set -e
|
||||
pids=$(pidof uwsgi || true)
|
||||
if [[ ! -z "$pids" ]]; then
|
||||
kill $pids || true
|
||||
sleep 1
|
||||
kill -9 $pids || true
|
||||
fi
|
||||
echo "Killed previous instance"
|
||||
|
||||
source $ENV_DIR/bin/activate
|
||||
exec uwsgi --master --die-on-term --socket :8000 --module bank_project.wsgi
|
|
@ -0,0 +1,21 @@
|
|||
# this config example is in the public domain
|
||||
|
||||
# the upstream component nginx needs to connect to
|
||||
upstream django {
|
||||
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
|
||||
server 127.0.0.1:8001; # for a web port socket (we'll use this first)
|
||||
}
|
||||
|
||||
# configuration of the server
|
||||
server {
|
||||
# the port your site will be served on
|
||||
listen 80;
|
||||
# the domain name it will serve for
|
||||
server_name localdjango; # substitute your machine's IP address or FQDN
|
||||
charset utf-8;
|
||||
|
||||
location / {
|
||||
uwsgi_pass django;
|
||||
include /home/marcello/static_test/uwsgi_params;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
uwsgi_param QUERY_STRING $query_string;
|
||||
uwsgi_param REQUEST_METHOD $request_method;
|
||||
uwsgi_param CONTENT_TYPE $content_type;
|
||||
uwsgi_param CONTENT_LENGTH $content_length;
|
||||
|
||||
uwsgi_param REQUEST_URI $request_uri;
|
||||
uwsgi_param PATH_INFO $document_uri;
|
||||
uwsgi_param DOCUMENT_ROOT $document_root;
|
||||
uwsgi_param SERVER_PROTOCOL $server_protocol;
|
||||
uwsgi_param REQUEST_SCHEME $scheme;
|
||||
uwsgi_param HTTPS $https if_not_empty;
|
||||
|
||||
uwsgi_param REMOTE_ADDR $remote_addr;
|
||||
uwsgi_param REMOTE_PORT $remote_port;
|
||||
uwsgi_param SERVER_PORT $server_port;
|
||||
uwsgi_param SERVER_NAME $server_name;
|
|
@ -0,0 +1,49 @@
|
|||
.Dd May 13, 2016
|
||||
.Dt TALER-BANK-MANAGE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm taler-bank-manage
|
||||
.Nd Manager script for the Taler bank
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl -django
|
||||
.Op Fl -serve-http
|
||||
.Op Fl -serve-uwsgi
|
||||
.Op Fl -sampledata
|
||||
.Op Fl -config
|
||||
.Ao Ar options Ac
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a command line tool to manage the Taler bank demonstrator.
|
||||
It is mandatory to provide a switch.
|
||||
Each switch has its own set of options.
|
||||
Give
|
||||
.Fl -help
|
||||
to each switch in order to get the list of supported options.
|
||||
.Ss SWITCHES
|
||||
.Bl -tag -width Ds
|
||||
.It Fl -django
|
||||
This switch is a mere wrapper for the django native tool
|
||||
.Xr django-admin 1 ,
|
||||
therefore it takes the same options.
|
||||
Refer to the official django-admin documentation.
|
||||
.It Fl -serve-http
|
||||
Launches the bank Web service at the port given in the
|
||||
.Fl -port
|
||||
option.
|
||||
.It Fl -serve-uwsgi
|
||||
Launches the bank over UWSGI.
|
||||
Typically used in conjunction with a Web server which acts like
|
||||
a reverse proxy.
|
||||
.It Fl -sampledata
|
||||
Populates the bank's database with sample wire transfers.
|
||||
.It Fl -config
|
||||
Shows all of Taler's configuration.
|
||||
it just retrieves values from default configuration files.
|
||||
.El
|
||||
.\".Sh EXAMPLES
|
||||
.Sh SEE ALSO
|
||||
.Xr django-admin 1
|
||||
.\".Sh HISTORY
|
||||
.\".Sh AUTHORS
|
||||
.\".Sh BUGS
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
def main():
|
||||
if "compilemessages" not in sys.argv and "makemessages" not in sys.argv:
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'talerbank.settings')
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -0,0 +1,687 @@
|
|||
[[package]]
|
||||
name = "appdirs"
|
||||
version = "1.4.4"
|
||||
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "asgiref"
|
||||
version = "3.3.4"
|
||||
description = "ASGI specs, helper code, and adapters"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.extras]
|
||||
tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"]
|
||||
|
||||
[[package]]
|
||||
name = "astroid"
|
||||
version = "2.5.6"
|
||||
description = "An abstract syntax tree for Python with inference support."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "~=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
lazy-object-proxy = ">=1.4.0"
|
||||
wrapt = ">=1.11,<1.13"
|
||||
|
||||
[[package]]
|
||||
name = "babel"
|
||||
version = "2.9.1"
|
||||
description = "Internationalization utilities"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[package.dependencies]
|
||||
pytz = ">=2015.7"
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "20.8b1"
|
||||
description = "The uncompromising code formatter."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
appdirs = "*"
|
||||
click = ">=7.1.2"
|
||||
mypy-extensions = ">=0.4.3"
|
||||
pathspec = ">=0.6,<1"
|
||||
regex = ">=2020.1.8"
|
||||
toml = ">=0.10.1"
|
||||
typed-ast = ">=1.4.0"
|
||||
typing-extensions = ">=3.7.4"
|
||||
|
||||
[package.extras]
|
||||
colorama = ["colorama (>=0.4.3)"]
|
||||
d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2020.12.5"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "chardet"
|
||||
version = "4.0.0"
|
||||
description = "Universal encoding detector for Python 2 and 3"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "7.1.2"
|
||||
description = "Composable command line interface toolkit"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.4"
|
||||
description = "Cross-platform colored terminal text."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "django"
|
||||
version = "3.2.3"
|
||||
description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
asgiref = ">=3.3.2,<4"
|
||||
pytz = "*"
|
||||
sqlparse = ">=0.2.2"
|
||||
|
||||
[package.extras]
|
||||
argon2 = ["argon2-cffi (>=19.1.0)"]
|
||||
bcrypt = ["bcrypt"]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "2.10"
|
||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "isort"
|
||||
version = "5.8.0"
|
||||
description = "A Python utility / library to sort Python imports."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6,<4.0"
|
||||
|
||||
[package.extras]
|
||||
pipfile_deprecated_finder = ["pipreqs", "requirementslib"]
|
||||
requirements_deprecated_finder = ["pipreqs", "pip-api"]
|
||||
colors = ["colorama (>=0.4.3,<0.5.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2"
|
||||
version = "3.0.0"
|
||||
description = "A very fast and expressive template engine."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
MarkupSafe = ">=2.0.0rc2"
|
||||
|
||||
[package.extras]
|
||||
i18n = ["Babel (>=2.7)"]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-object-proxy"
|
||||
version = "1.6.0"
|
||||
description = "A fast and thorough lazy object proxy."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
|
||||
|
||||
[[package]]
|
||||
name = "lxml"
|
||||
version = "4.6.3"
|
||||
description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*"
|
||||
|
||||
[package.extras]
|
||||
cssselect = ["cssselect (>=0.7)"]
|
||||
html5 = ["html5lib"]
|
||||
htmlsoup = ["beautifulsoup4"]
|
||||
source = ["Cython (>=0.29.7)"]
|
||||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "2.0.1"
|
||||
description = "Safely add untrusted strings to HTML/XML markup."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "mccabe"
|
||||
version = "0.6.1"
|
||||
description = "McCabe checker, plugin for flake8"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "mock"
|
||||
version = "4.0.3"
|
||||
description = "Rolling backport of unittest.mock for all Pythons"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.extras]
|
||||
build = ["twine", "wheel", "blurb"]
|
||||
docs = ["sphinx"]
|
||||
test = ["pytest (<5.4)", "pytest-cov"]
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "0.4.3"
|
||||
description = "Experimental type system extensions for programs checked with the mypy typechecker."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.8.1"
|
||||
description = "Utility library for gitignore style pattern matching of file paths."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "psycopg2"
|
||||
version = "2.8.6"
|
||||
description = "psycopg2 - Python-PostgreSQL Database Adapter"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "pylint"
|
||||
version = "2.8.2"
|
||||
description = "python code static checker"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "~=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
astroid = ">=2.5.6,<2.7"
|
||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||
isort = ">=4.2.5,<6"
|
||||
mccabe = ">=0.6,<0.7"
|
||||
toml = ">=0.7.1"
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2021.1"
|
||||
description = "World timezone definitions, modern and historical"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "qrcode"
|
||||
version = "6.1"
|
||||
description = "QR Code image generator"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
six = "*"
|
||||
|
||||
[package.extras]
|
||||
dev = ["tox", "pytest", "mock"]
|
||||
maintainer = ["zest.releaser"]
|
||||
pil = ["pillow"]
|
||||
test = ["pytest", "pytest-cov", "mock"]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "2021.4.4"
|
||||
description = "Alternative regular expression module, to replace re."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.25.1"
|
||||
description = "Python HTTP for Humans."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
chardet = ">=3.0.2,<5"
|
||||
idna = ">=2.5,<3"
|
||||
urllib3 = ">=1.21.1,<1.27"
|
||||
|
||||
[package.extras]
|
||||
security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.16.0"
|
||||
description = "Python 2 and 3 compatibility utilities"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[[package]]
|
||||
name = "sqlparse"
|
||||
version = "0.4.1"
|
||||
description = "A non-validating SQL parser."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[[package]]
|
||||
name = "taler-util"
|
||||
version = "0.8.3"
|
||||
description = "Util library for GNU Taler"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.10.2"
|
||||
description = "Python Library for Tom's Obvious, Minimal Language"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[[package]]
|
||||
name = "typed-ast"
|
||||
version = "1.4.3"
|
||||
description = "a fork of Python 2 and 3 ast modules with type comment support"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "3.10.0.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.5+"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "1.26.4"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
|
||||
|
||||
[package.extras]
|
||||
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
brotli = ["brotlipy (>=0.6.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "uwsgi"
|
||||
version = "2.0.19.1"
|
||||
description = "The uWSGI server"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "wrapt"
|
||||
version = "1.12.1"
|
||||
description = "Module for decorators, wrappers and monkey patching."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.8"
|
||||
content-hash = "9774137a0dd606c6a3608f64563d91bbbfc000695d8a13d397e4b57318a204c6"
|
||||
|
||||
[metadata.files]
|
||||
appdirs = [
|
||||
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
|
||||
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
|
||||
]
|
||||
asgiref = [
|
||||
{file = "asgiref-3.3.4-py3-none-any.whl", hash = "sha256:92906c611ce6c967347bbfea733f13d6313901d54dcca88195eaeb52b2a8e8ee"},
|
||||
{file = "asgiref-3.3.4.tar.gz", hash = "sha256:d1216dfbdfb63826470995d31caed36225dcaf34f182e0fa257a4dd9e86f1b78"},
|
||||
]
|
||||
astroid = [
|
||||
{file = "astroid-2.5.6-py3-none-any.whl", hash = "sha256:4db03ab5fc3340cf619dbc25e42c2cc3755154ce6009469766d7143d1fc2ee4e"},
|
||||
{file = "astroid-2.5.6.tar.gz", hash = "sha256:8a398dfce302c13f14bab13e2b14fe385d32b73f4e4853b9bdfb64598baa1975"},
|
||||
]
|
||||
babel = [
|
||||
{file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"},
|
||||
{file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"},
|
||||
]
|
||||
black = [
|
||||
{file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"},
|
||||
]
|
||||
certifi = [
|
||||
{file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"},
|
||||
{file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"},
|
||||
]
|
||||
chardet = [
|
||||
{file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"},
|
||||
{file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
|
||||
]
|
||||
click = [
|
||||
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
|
||||
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
|
||||
]
|
||||
colorama = [
|
||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
||||
]
|
||||
django = [
|
||||
{file = "Django-3.2.3-py3-none-any.whl", hash = "sha256:7e0a1393d18c16b503663752a8b6790880c5084412618990ce8a81cc908b4962"},
|
||||
{file = "Django-3.2.3.tar.gz", hash = "sha256:13ac78dbfd189532cad8f383a27e58e18b3d33f80009ceb476d7fcbfc5dcebd8"},
|
||||
]
|
||||
idna = [
|
||||
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
|
||||
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
|
||||
]
|
||||
isort = [
|
||||
{file = "isort-5.8.0-py3-none-any.whl", hash = "sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d"},
|
||||
{file = "isort-5.8.0.tar.gz", hash = "sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6"},
|
||||
]
|
||||
jinja2 = [
|
||||
{file = "Jinja2-3.0.0-py3-none-any.whl", hash = "sha256:2f2de5285cf37f33d33ecd4a9080b75c87cd0c1994d5a9c6df17131ea1f049c6"},
|
||||
{file = "Jinja2-3.0.0.tar.gz", hash = "sha256:ea8d7dd814ce9df6de6a761ec7f1cac98afe305b8cdc4aaae4e114b8d8ce24c5"},
|
||||
]
|
||||
lazy-object-proxy = [
|
||||
{file = "lazy-object-proxy-1.6.0.tar.gz", hash = "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp27-cp27m-win32.whl", hash = "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp36-cp36m-win32.whl", hash = "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp37-cp37m-win32.whl", hash = "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp38-cp38-win32.whl", hash = "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp39-cp39-win32.whl", hash = "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61"},
|
||||
{file = "lazy_object_proxy-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"},
|
||||
]
|
||||
lxml = [
|
||||
{file = "lxml-4.6.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:df7c53783a46febb0e70f6b05df2ba104610f2fb0d27023409734a3ecbb78fb2"},
|
||||
{file = "lxml-4.6.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1b7584d421d254ab86d4f0b13ec662a9014397678a7c4265a02a6d7c2b18a75f"},
|
||||
{file = "lxml-4.6.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:079f3ae844f38982d156efce585bc540c16a926d4436712cf4baee0cce487a3d"},
|
||||
{file = "lxml-4.6.3-cp27-cp27m-win32.whl", hash = "sha256:bc4313cbeb0e7a416a488d72f9680fffffc645f8a838bd2193809881c67dd106"},
|
||||
{file = "lxml-4.6.3-cp27-cp27m-win_amd64.whl", hash = "sha256:8157dadbb09a34a6bd95a50690595e1fa0af1a99445e2744110e3dca7831c4ee"},
|
||||
{file = "lxml-4.6.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7728e05c35412ba36d3e9795ae8995e3c86958179c9770e65558ec3fdfd3724f"},
|
||||
{file = "lxml-4.6.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4bff24dfeea62f2e56f5bab929b4428ae6caba2d1eea0c2d6eb618e30a71e6d4"},
|
||||
{file = "lxml-4.6.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:74f7d8d439b18fa4c385f3f5dfd11144bb87c1da034a466c5b5577d23a1d9b51"},
|
||||
{file = "lxml-4.6.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f90ba11136bfdd25cae3951af8da2e95121c9b9b93727b1b896e3fa105b2f586"},
|
||||
{file = "lxml-4.6.3-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:4c61b3a0db43a1607d6264166b230438f85bfed02e8cff20c22e564d0faff354"},
|
||||
{file = "lxml-4.6.3-cp35-cp35m-manylinux2014_x86_64.whl", hash = "sha256:5c8c163396cc0df3fd151b927e74f6e4acd67160d6c33304e805b84293351d16"},
|
||||
{file = "lxml-4.6.3-cp35-cp35m-win32.whl", hash = "sha256:f2380a6376dfa090227b663f9678150ef27543483055cc327555fb592c5967e2"},
|
||||
{file = "lxml-4.6.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c4f05c5a7c49d2fb70223d0d5bcfbe474cf928310ac9fa6a7c6dddc831d0b1d4"},
|
||||
{file = "lxml-4.6.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d2e35d7bf1c1ac8c538f88d26b396e73dd81440d59c1ef8522e1ea77b345ede4"},
|
||||
{file = "lxml-4.6.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:289e9ca1a9287f08daaf796d96e06cb2bc2958891d7911ac7cae1c5f9e1e0ee3"},
|
||||
{file = "lxml-4.6.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bccbfc27563652de7dc9bdc595cb25e90b59c5f8e23e806ed0fd623755b6565d"},
|
||||
{file = "lxml-4.6.3-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d916d31fd85b2f78c76400d625076d9124de3e4bda8b016d25a050cc7d603f24"},
|
||||
{file = "lxml-4.6.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:820628b7b3135403540202e60551e741f9b6d3304371712521be939470b454ec"},
|
||||
{file = "lxml-4.6.3-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:c47ff7e0a36d4efac9fd692cfa33fbd0636674c102e9e8d9b26e1b93a94e7617"},
|
||||
{file = "lxml-4.6.3-cp36-cp36m-win32.whl", hash = "sha256:5a0a14e264069c03e46f926be0d8919f4105c1623d620e7ec0e612a2e9bf1c04"},
|
||||
{file = "lxml-4.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:92e821e43ad382332eade6812e298dc9701c75fe289f2a2d39c7960b43d1e92a"},
|
||||
{file = "lxml-4.6.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efd7a09678fd8b53117f6bae4fa3825e0a22b03ef0a932e070c0bdbb3a35e654"},
|
||||
{file = "lxml-4.6.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:efac139c3f0bf4f0939f9375af4b02c5ad83a622de52d6dfa8e438e8e01d0eb0"},
|
||||
{file = "lxml-4.6.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0fbcf5565ac01dff87cbfc0ff323515c823081c5777a9fc7703ff58388c258c3"},
|
||||
{file = "lxml-4.6.3-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:36108c73739985979bf302006527cf8a20515ce444ba916281d1c43938b8bb96"},
|
||||
{file = "lxml-4.6.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:122fba10466c7bd4178b07dba427aa516286b846b2cbd6f6169141917283aae2"},
|
||||
{file = "lxml-4.6.3-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:cdaf11d2bd275bf391b5308f86731e5194a21af45fbaaaf1d9e8147b9160ea92"},
|
||||
{file = "lxml-4.6.3-cp37-cp37m-win32.whl", hash = "sha256:3439c71103ef0e904ea0a1901611863e51f50b5cd5e8654a151740fde5e1cade"},
|
||||
{file = "lxml-4.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:4289728b5e2000a4ad4ab8da6e1db2e093c63c08bdc0414799ee776a3f78da4b"},
|
||||
{file = "lxml-4.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b007cbb845b28db4fb8b6a5cdcbf65bacb16a8bd328b53cbc0698688a68e1caa"},
|
||||
{file = "lxml-4.6.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:76fa7b1362d19f8fbd3e75fe2fb7c79359b0af8747e6f7141c338f0bee2f871a"},
|
||||
{file = "lxml-4.6.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:26e761ab5b07adf5f555ee82fb4bfc35bf93750499c6c7614bd64d12aaa67927"},
|
||||
{file = "lxml-4.6.3-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:e1cbd3f19a61e27e011e02f9600837b921ac661f0c40560eefb366e4e4fb275e"},
|
||||
{file = "lxml-4.6.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:66e575c62792c3f9ca47cb8b6fab9e35bab91360c783d1606f758761810c9791"},
|
||||
{file = "lxml-4.6.3-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:1b38116b6e628118dea5b2186ee6820ab138dbb1e24a13e478490c7db2f326ae"},
|
||||
{file = "lxml-4.6.3-cp38-cp38-win32.whl", hash = "sha256:89b8b22a5ff72d89d48d0e62abb14340d9e99fd637d046c27b8b257a01ffbe28"},
|
||||
{file = "lxml-4.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:2a9d50e69aac3ebee695424f7dbd7b8c6d6eb7de2a2eb6b0f6c7db6aa41e02b7"},
|
||||
{file = "lxml-4.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ce256aaa50f6cc9a649c51be3cd4ff142d67295bfc4f490c9134d0f9f6d58ef0"},
|
||||
{file = "lxml-4.6.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:7610b8c31688f0b1be0ef882889817939490a36d0ee880ea562a4e1399c447a1"},
|
||||
{file = "lxml-4.6.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f8380c03e45cf09f8557bdaa41e1fa7c81f3ae22828e1db470ab2a6c96d8bc23"},
|
||||
{file = "lxml-4.6.3-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:3082c518be8e97324390614dacd041bb1358c882d77108ca1957ba47738d9d59"},
|
||||
{file = "lxml-4.6.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:884ab9b29feaca361f7f88d811b1eea9bfca36cf3da27768d28ad45c3ee6f969"},
|
||||
{file = "lxml-4.6.3-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:6f12e1427285008fd32a6025e38e977d44d6382cf28e7201ed10d6c1698d2a9a"},
|
||||
{file = "lxml-4.6.3-cp39-cp39-win32.whl", hash = "sha256:33bb934a044cf32157c12bfcfbb6649807da20aa92c062ef51903415c704704f"},
|
||||
{file = "lxml-4.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:542d454665a3e277f76954418124d67516c5f88e51a900365ed54a9806122b83"},
|
||||
{file = "lxml-4.6.3.tar.gz", hash = "sha256:39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468"},
|
||||
]
|
||||
markupsafe = [
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
|
||||
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
|
||||
]
|
||||
mccabe = [
|
||||
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
|
||||
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
|
||||
]
|
||||
mock = [
|
||||
{file = "mock-4.0.3-py3-none-any.whl", hash = "sha256:122fcb64ee37cfad5b3f48d7a7d51875d7031aaf3d8be7c42e2bee25044eee62"},
|
||||
{file = "mock-4.0.3.tar.gz", hash = "sha256:7d3fbbde18228f4ff2f1f119a45cdffa458b4c0dee32eb4d2bb2f82554bac7bc"},
|
||||
]
|
||||
mypy-extensions = [
|
||||
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
||||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||
]
|
||||
pathspec = [
|
||||
{file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"},
|
||||
{file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"},
|
||||
]
|
||||
psycopg2 = [
|
||||
{file = "psycopg2-2.8.6-cp27-cp27m-win32.whl", hash = "sha256:068115e13c70dc5982dfc00c5d70437fe37c014c808acce119b5448361c03725"},
|
||||
{file = "psycopg2-2.8.6-cp27-cp27m-win_amd64.whl", hash = "sha256:d160744652e81c80627a909a0e808f3c6653a40af435744de037e3172cf277f5"},
|
||||
{file = "psycopg2-2.8.6-cp34-cp34m-win32.whl", hash = "sha256:b8cae8b2f022efa1f011cc753adb9cbadfa5a184431d09b273fb49b4167561ad"},
|
||||
{file = "psycopg2-2.8.6-cp34-cp34m-win_amd64.whl", hash = "sha256:f22ea9b67aea4f4a1718300908a2fb62b3e4276cf00bd829a97ab5894af42ea3"},
|
||||
{file = "psycopg2-2.8.6-cp35-cp35m-win32.whl", hash = "sha256:26e7fd115a6db75267b325de0fba089b911a4a12ebd3d0b5e7acb7028bc46821"},
|
||||
{file = "psycopg2-2.8.6-cp35-cp35m-win_amd64.whl", hash = "sha256:00195b5f6832dbf2876b8bf77f12bdce648224c89c880719c745b90515233301"},
|
||||
{file = "psycopg2-2.8.6-cp36-cp36m-win32.whl", hash = "sha256:a49833abfdede8985ba3f3ec641f771cca215479f41523e99dace96d5b8cce2a"},
|
||||
{file = "psycopg2-2.8.6-cp36-cp36m-win_amd64.whl", hash = "sha256:f974c96fca34ae9e4f49839ba6b78addf0346777b46c4da27a7bf54f48d3057d"},
|
||||
{file = "psycopg2-2.8.6-cp37-cp37m-win32.whl", hash = "sha256:6a3d9efb6f36f1fe6aa8dbb5af55e067db802502c55a9defa47c5a1dad41df84"},
|
||||
{file = "psycopg2-2.8.6-cp37-cp37m-win_amd64.whl", hash = "sha256:56fee7f818d032f802b8eed81ef0c1232b8b42390df189cab9cfa87573fe52c5"},
|
||||
{file = "psycopg2-2.8.6-cp38-cp38-win32.whl", hash = "sha256:ad2fe8a37be669082e61fb001c185ffb58867fdbb3e7a6b0b0d2ffe232353a3e"},
|
||||
{file = "psycopg2-2.8.6-cp38-cp38-win_amd64.whl", hash = "sha256:56007a226b8e95aa980ada7abdea6b40b75ce62a433bd27cec7a8178d57f4051"},
|
||||
{file = "psycopg2-2.8.6-cp39-cp39-win32.whl", hash = "sha256:2c93d4d16933fea5bbacbe1aaf8fa8c1348740b2e50b3735d1b0bf8154cbf0f3"},
|
||||
{file = "psycopg2-2.8.6-cp39-cp39-win_amd64.whl", hash = "sha256:d5062ae50b222da28253059880a871dc87e099c25cb68acf613d9d227413d6f7"},
|
||||
{file = "psycopg2-2.8.6.tar.gz", hash = "sha256:fb23f6c71107c37fd667cb4ea363ddeb936b348bbd6449278eb92c189699f543"},
|
||||
]
|
||||
pylint = [
|
||||
{file = "pylint-2.8.2-py3-none-any.whl", hash = "sha256:f7e2072654a6b6afdf5e2fb38147d3e2d2d43c89f648637baab63e026481279b"},
|
||||
{file = "pylint-2.8.2.tar.gz", hash = "sha256:586d8fa9b1891f4b725f587ef267abe2a1bad89d6b184520c7f07a253dd6e217"},
|
||||
]
|
||||
pytz = [
|
||||
{file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
|
||||
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
|
||||
]
|
||||
qrcode = [
|
||||
{file = "qrcode-6.1-py2.py3-none-any.whl", hash = "sha256:3996ee560fc39532910603704c82980ff6d4d5d629f9c3f25f34174ce8606cf5"},
|
||||
{file = "qrcode-6.1.tar.gz", hash = "sha256:505253854f607f2abf4d16092c61d4e9d511a3b4392e60bff957a68592b04369"},
|
||||
]
|
||||
regex = [
|
||||
{file = "regex-2021.4.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:619d71c59a78b84d7f18891fe914446d07edd48dc8328c8e149cbe0929b4e000"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:47bf5bf60cf04d72bf6055ae5927a0bd9016096bf3d742fa50d9bf9f45aa0711"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:281d2fd05555079448537fe108d79eb031b403dac622621c78944c235f3fcf11"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:bd28bc2e3a772acbb07787c6308e00d9626ff89e3bfcdebe87fa5afbfdedf968"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7c2a1af393fcc09e898beba5dd59196edaa3116191cc7257f9224beaed3e1aa0"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c38c71df845e2aabb7fb0b920d11a1b5ac8526005e533a8920aea97efb8ec6a4"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:96fcd1888ab4d03adfc9303a7b3c0bd78c5412b2bfbe76db5b56d9eae004907a"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:ade17eb5d643b7fead300a1641e9f45401c98eee23763e9ed66a43f92f20b4a7"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-win32.whl", hash = "sha256:e8e5b509d5c2ff12f8418006d5a90e9436766133b564db0abaec92fd27fcee29"},
|
||||
{file = "regex-2021.4.4-cp36-cp36m-win_amd64.whl", hash = "sha256:11d773d75fa650cd36f68d7ca936e3c7afaae41b863b8c387a22aaa78d3c5c79"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d3029c340cfbb3ac0a71798100ccc13b97dddf373a4ae56b6a72cf70dfd53bc8"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:18c071c3eb09c30a264879f0d310d37fe5d3a3111662438889ae2eb6fc570c31"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:4c557a7b470908b1712fe27fb1ef20772b78079808c87d20a90d051660b1d69a"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:01afaf2ec48e196ba91b37451aa353cb7eda77efe518e481707e0515025f0cd5"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:3a9cd17e6e5c7eb328517969e0cb0c3d31fd329298dd0c04af99ebf42e904f82"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:90f11ff637fe8798933fb29f5ae1148c978cccb0452005bf4c69e13db951e765"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:919859aa909429fb5aa9cf8807f6045592c85ef56fdd30a9a3747e513db2536e"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:339456e7d8c06dd36a22e451d58ef72cef293112b559010db3d054d5560ef439"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-win32.whl", hash = "sha256:67bdb9702427ceddc6ef3dc382455e90f785af4c13d495f9626861763ee13f9d"},
|
||||
{file = "regex-2021.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:32e65442138b7b76dd8173ffa2cf67356b7bc1768851dded39a7a13bf9223da3"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1e1c20e29358165242928c2de1482fb2cf4ea54a6a6dea2bd7a0e0d8ee321500"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:314d66636c494ed9c148a42731b3834496cc9a2c4251b1661e40936814542b14"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6d1b01031dedf2503631d0903cb563743f397ccaf6607a5e3b19a3d76fc10480"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:741a9647fcf2e45f3a1cf0e24f5e17febf3efe8d4ba1281dcc3aa0459ef424dc"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4c46e22a0933dd783467cf32b3516299fb98cfebd895817d685130cc50cd1093"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:e512d8ef5ad7b898cdb2d8ee1cb09a8339e4f8be706d27eaa180c2f177248a10"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:980d7be47c84979d9136328d882f67ec5e50008681d94ecc8afa8a65ed1f4a6f"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:ce15b6d103daff8e9fee13cf7f0add05245a05d866e73926c358e871221eae87"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-win32.whl", hash = "sha256:a91aa8619b23b79bcbeb37abe286f2f408d2f2d6f29a17237afda55bb54e7aac"},
|
||||
{file = "regex-2021.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:c0502c0fadef0d23b128605d69b58edb2c681c25d44574fc673b0e52dce71ee2"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:598585c9f0af8374c28edd609eb291b5726d7cbce16be6a8b95aa074d252ee17"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:ee54ff27bf0afaf4c3b3a62bcd016c12c3fdb4ec4f413391a90bd38bc3624605"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7d9884d86dd4dd489e981d94a65cd30d6f07203d90e98f6f657f05170f6324c9"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:bf5824bfac591ddb2c1f0a5f4ab72da28994548c708d2191e3b87dd207eb3ad7"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:563085e55b0d4fb8f746f6a335893bda5c2cef43b2f0258fe1020ab1dd874df8"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9c3db21af35e3b3c05764461b262d6f05bbca08a71a7849fd79d47ba7bc33ed"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:3916d08be28a1149fb97f7728fca1f7c15d309a9f9682d89d79db75d5e52091c"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:fd45ff9293d9274c5008a2054ecef86a9bfe819a67c7be1afb65e69b405b3042"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-win32.whl", hash = "sha256:fa4537fb4a98fe8fde99626e4681cc644bdcf2a795038533f9f711513a862ae6"},
|
||||
{file = "regex-2021.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:97f29f57d5b84e73fbaf99ab3e26134e6687348e95ef6b48cfd2c06807005a07"},
|
||||
{file = "regex-2021.4.4.tar.gz", hash = "sha256:52ba3d3f9b942c49d7e4bc105bb28551c44065f139a65062ab7912bef10c9afb"},
|
||||
]
|
||||
requests = [
|
||||
{file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"},
|
||||
{file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"},
|
||||
]
|
||||
six = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
]
|
||||
sqlparse = [
|
||||
{file = "sqlparse-0.4.1-py3-none-any.whl", hash = "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0"},
|
||||
{file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"},
|
||||
]
|
||||
taler-util = [
|
||||
{file = "taler-util-0.8.3.tar.gz", hash = "sha256:3ff81faf6dff494ae1727d47cec9d853d8719f9d5325a1e7775fa3cc9ded88c1"},
|
||||
{file = "taler_util-0.8.3-py3-none-any.whl", hash = "sha256:b00105961024ce73f3142aaa6379e17251815ce7bc4b3a472d91efd9089a5003"},
|
||||
]
|
||||
toml = [
|
||||
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||
]
|
||||
typed-ast = [
|
||||
{file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"},
|
||||
{file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"},
|
||||
{file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"},
|
||||
{file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"},
|
||||
{file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"},
|
||||
{file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"},
|
||||
]
|
||||
typing-extensions = [
|
||||
{file = "typing_extensions-3.10.0.0-py2-none-any.whl", hash = "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497"},
|
||||
{file = "typing_extensions-3.10.0.0-py3-none-any.whl", hash = "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"},
|
||||
{file = "typing_extensions-3.10.0.0.tar.gz", hash = "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342"},
|
||||
]
|
||||
urllib3 = [
|
||||
{file = "urllib3-1.26.4-py2.py3-none-any.whl", hash = "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df"},
|
||||
{file = "urllib3-1.26.4.tar.gz", hash = "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"},
|
||||
]
|
||||
uwsgi = [
|
||||
{file = "uWSGI-2.0.19.1.tar.gz", hash = "sha256:faa85e053c0b1be4d5585b0858d3a511d2cd10201802e8676060fd0a109e5869"},
|
||||
]
|
||||
wrapt = [
|
||||
{file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"},
|
||||
]
|
|
@ -0,0 +1,34 @@
|
|||
[tool.poetry]
|
||||
name = "talerbank"
|
||||
version = "0.8.2"
|
||||
description = "Taler demo bank"
|
||||
authors = ["Marcello Stanisci <ms@taler.net>", "Florian Dold <dold@taler.net"]
|
||||
license = "GPL-3.0-or-later"
|
||||
include = ["talerbank/app/locale/*/LC_MESSAGES/django.mo"]
|
||||
exclude = ["talerbank/app/locale/*/LC_MESSAGES/django.po"]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.8"
|
||||
django = "^3.1.3"
|
||||
taler-util = "^0.8.3"
|
||||
lxml = "^4.6.1"
|
||||
psycopg2 = "^2.8.6"
|
||||
Jinja2 = "^3.0.0"
|
||||
qrcode = "^6.1"
|
||||
uWSGI = "^2.0.19"
|
||||
requests = "^2.24.0"
|
||||
click = "^7.1.2"
|
||||
Babel = "^2.8.0"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pylint = "^2.6.0"
|
||||
django = "^3.1.3"
|
||||
black = "^20.8b1"
|
||||
mock = "^4.0.2"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
taler-bank-manage = 'talerbank.cli:run'
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry>=0.12"]
|
||||
build-backend = "poetry.masonry.api"
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# See Bug #5850 for some tests that are currently skipped
|
||||
|
||||
if [[ -z $1 ]]; then
|
||||
echo "Usage: ./run-one-test.sh 'TestClassName'"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
export TALER_CONFIG_FILE="talerbank/app/testconfigs/bank-check.conf"
|
||||
exec ./manage.py test --no-input talerbank.app.tests.$1
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# See Bug #5850 for some tests that are currently skipped
|
||||
|
||||
export TALER_CONFIG_FILE="talerbank/app/testconfigs/bank-check.conf"
|
||||
exec ./manage.py test --no-input talerbank.app.tests "$@"
|
|
@ -0,0 +1,4 @@
|
|||
import logging
|
||||
|
||||
FMT = "%(asctime)-15s %(module)s %(levelname)s %(message)s"
|
||||
logging.basicConfig(format=FMT, level=logging.WARNING)
|
|
@ -0,0 +1,7 @@
|
|||
# This file is in the public domain
|
||||
|
||||
from django.contrib import admin
|
||||
from .models import BankAccount, BankTransaction
|
||||
|
||||
admin.site.register(BankAccount)
|
||||
admin.site.register(BankTransaction)
|
|
@ -0,0 +1,321 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-20 07:51+0000\n"
|
||||
"PO-Revision-Date: 2021-01-30 10:01+0000\n"
|
||||
"Last-Translator: Weblate Admin <admin@example.com>\n"
|
||||
"Language-Team: German <http://weblate.taler.net/projects/gnu-taler/"
|
||||
"taler-bank/de/>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.4.2\n"
|
||||
|
||||
#: talerbank/app/templates/404.html:23
|
||||
msgid "Error"
|
||||
msgstr "Fehler"
|
||||
|
||||
#: talerbank/app/templates/404.html:30
|
||||
msgid "Page not found!"
|
||||
msgstr "Die Seite wurde nicht gefunden!"
|
||||
|
||||
#: talerbank/app/templates/base.html:23
|
||||
#, python-brace-format
|
||||
msgid "{currency} Bank - Taler Demo"
|
||||
msgstr "{currency} Bank - Taler Demo"
|
||||
|
||||
#: talerbank/app/templates/base.html:74
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"This part of the demo shows how a bank that supports Taler directly would "
|
||||
"work. In addition to using your own bank account, you can also see the "
|
||||
"transaction history of some <a href=\"{public_accounts}\">Public Accounts</"
|
||||
"a>."
|
||||
msgstr ""
|
||||
"Die Demo-Seiten der Bank veranschaulichen, wie sich die Buchungen mit GNU "
|
||||
"Taler auf verschiedenen Bankkonten auswirken. Durch Klicken auf die "
|
||||
"Tabulatoren erhält man eine Liste der Buchungen in einzelnen <a href=\""
|
||||
"{public_accounts}\">öffentlich sichtbaren Konten</a>: Für den Exchange, die "
|
||||
"Bank, den Umfrage-Anbieter (Tipping/Survey-Beispiel) und andere Bankkunden. "
|
||||
"Die Zahlungsströme sind leicht nachvollziehbar, wenn man diese Buchungen mit "
|
||||
"den Buchungen auf dem eigenen Konto, von dem die Geldwerte abgebucht wurden, "
|
||||
"in Beziehung setzt."
|
||||
|
||||
#: talerbank/app/templates/base.html:80
|
||||
msgid "Introduction"
|
||||
msgstr "Einführung"
|
||||
|
||||
#: talerbank/app/templates/base.html:81
|
||||
msgid "Bank"
|
||||
msgstr "Bank"
|
||||
|
||||
#: talerbank/app/templates/base.html:82
|
||||
msgid "Essay Shop"
|
||||
msgstr "Aufsatzsammlung"
|
||||
|
||||
#: talerbank/app/templates/base.html:83
|
||||
msgid "Donations"
|
||||
msgstr "Spenden"
|
||||
|
||||
#: talerbank/app/templates/base.html:84
|
||||
msgid "Tipping/Survey"
|
||||
msgstr "Tipping/Umfrage"
|
||||
|
||||
#: talerbank/app/templates/base.html:94
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"You can learn more about Taler on our main <a href={taler_site}>website</a>."
|
||||
msgstr ""
|
||||
"Alles Wissenswerte zu GNU Taler gibt es auf unseren <a "
|
||||
"href={taler_site}>Webseiten</a>."
|
||||
|
||||
#: talerbank/app/templates/login.html:22
|
||||
#, python-brace-format
|
||||
msgid "Welcome to the {currency} Bank!"
|
||||
msgstr "Willkommen bei der {currency} Bank!"
|
||||
|
||||
#: talerbank/app/templates/login.html:29
|
||||
msgid "Please login!"
|
||||
msgstr "Bitte melden Sie sich an!"
|
||||
|
||||
#: talerbank/app/templates/login.html:33
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr "Nutzername / Passwort abgelehnt. Bitte nochmals versuchen."
|
||||
|
||||
#: talerbank/app/templates/login.html:40
|
||||
msgid ""
|
||||
"Your account doesn't have access to this page. To proceed, please login with "
|
||||
"an account that has access."
|
||||
msgstr ""
|
||||
"Ihr Konto hat keinen Zugang zu dieser Seite. Bitte melden Sie sich mit einem "
|
||||
"Konto an, das zum Zugang berechtigt ist."
|
||||
|
||||
#: talerbank/app/templates/login.html:43
|
||||
msgid "Please login to see this page."
|
||||
msgstr "Bitte melden Sie sich an."
|
||||
|
||||
#: talerbank/app/templates/login.html:59
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"If you are a new customer please <a href=\"{register_link}\">register</a>. "
|
||||
"Registration is fast and free, and it gives you a registration bonus of 100 "
|
||||
"{currency}"
|
||||
msgstr ""
|
||||
"Wenn Sie noch kein Bankkonto haben, registrieren Sie sich bitte unter <a "
|
||||
"href=\"{register_link}\">Registrierung</a>. Die Eröffnung eines Konto "
|
||||
"geschieht einfach und schnell und belohnt Sie mit einem Startguthaben von "
|
||||
"100 {currency}."
|
||||
|
||||
#: talerbank/app/templates/login.html:63
|
||||
msgid "Registrations are not open to the public."
|
||||
msgstr ""
|
||||
"Die Registrierungsdaten sind nichtöffentlich und auch nicht von Dritten "
|
||||
"einsehbar."
|
||||
|
||||
#: talerbank/app/templates/login.html:67
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"To view transactions of public accounts, please <a href="
|
||||
"\"{public_accounts}\">click here</a>."
|
||||
msgstr ""
|
||||
"Bitte betrachten Sie die <a href=\"{public_accounts}\">öffentlich sichtbaren "
|
||||
"Konten</a>, um die Überweisungen vom Treuhandkonto des Exchange an die "
|
||||
"Bankkonten der Zahlungsempfänger zu sehen."
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:23
|
||||
#: talerbank/app/templates/profile_page.html:28
|
||||
msgid "Logout"
|
||||
msgstr "Ausloggen"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:30
|
||||
msgid "Wire transfer"
|
||||
msgstr "Überweisung"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:31
|
||||
msgid "Transfer money via the payto system:"
|
||||
msgstr ""
|
||||
"Geld überweisen mit dem payto-Schema (Uniform Resource Identifier gemäß RFC "
|
||||
"8905):"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:41
|
||||
msgid "payto address"
|
||||
msgstr "payto-Adresse"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:45
|
||||
msgid "Confirm"
|
||||
msgstr "Bestätigen"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:25
|
||||
#, python-brace-format
|
||||
msgid "Welcome <em>{name}</em>!"
|
||||
msgstr "Willkommen <em>{name}</em>!"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:33
|
||||
msgid "Bank account balance"
|
||||
msgstr "Kontostand"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:51
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr "Geld in ein Taler-Wallet abheben"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:58
|
||||
msgid "Amount to withdraw"
|
||||
msgstr "Abzuhebender Betrag"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:73
|
||||
msgid "Start withdrawal"
|
||||
msgstr "Abhebevorgang auslösen"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:78
|
||||
msgid "Wire money"
|
||||
msgstr "Geld überweisen"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:81
|
||||
msgid "Transactions for"
|
||||
msgstr "Transaktionen für"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:87
|
||||
#: talerbank/app/templates/public_accounts.html:59
|
||||
msgid "Date"
|
||||
msgstr "Datum"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:88
|
||||
#: talerbank/app/templates/public_accounts.html:60
|
||||
msgid "Amount"
|
||||
msgstr "Betrag"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:89
|
||||
#: talerbank/app/templates/public_accounts.html:61
|
||||
msgid "Counterpart"
|
||||
msgstr "Empfänger"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:90
|
||||
#: talerbank/app/templates/public_accounts.html:62
|
||||
msgid "Subject"
|
||||
msgstr "Verwendungszweck"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:107
|
||||
msgid "cancelled"
|
||||
msgstr "abgebrochen"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:116
|
||||
msgid "No transactions made to/from this account"
|
||||
msgstr "Keine Transaktionen zu / von diesem Konto"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:21
|
||||
msgid "History of public accounts"
|
||||
msgstr "Buchungen auf öffentlich sichtbaren Konten"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:71
|
||||
msgid "account"
|
||||
msgstr "Konto"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:101
|
||||
#, python-brace-format
|
||||
msgid "No history for account #{account_number} ({account_name}) yet"
|
||||
msgstr ""
|
||||
"Keine Bewegungen für Konto Nr. {account_number} ({account_name}) anzuzeigen."
|
||||
|
||||
#: talerbank/app/templates/register.html:22
|
||||
#, python-brace-format
|
||||
msgid "Register to the {currency} bank!"
|
||||
msgstr "Bitte eröffnen Sie ein Konto bei der {currency}-Bank!"
|
||||
|
||||
#: talerbank/app/templates/register.html:30
|
||||
msgid "Back"
|
||||
msgstr "Zurück"
|
||||
|
||||
#: talerbank/app/templates/register.html:39
|
||||
msgid ""
|
||||
"Sorry, this username is no longer available. Please choose another one!"
|
||||
msgstr ""
|
||||
"Diese Nutzerkennung ist nicht mehr verfügbar, bitte wählen Sie eine andere!"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:23
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr "Abhebung bestätigen"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:34
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{currency} Bank needs to verify that you intend to withdraw <b>{amount}</b> "
|
||||
"from <b>{exchange}</b>. To prove that you are the account owner, please "
|
||||
"answer the following "security question" (*):"
|
||||
msgstr ""
|
||||
"Die {currency}-Bank bittet Sie um Bestätigung, dass Sie den Betrag von "
|
||||
"<b>{amount}</b> des Exchange <b>{exchange}</b> in Ihr Wallet abheben wollen. "
|
||||
"Um zu beweisen, dass das Bankkonto Ihnen gehört, beantworten Sie bitte "
|
||||
"folgende ‚Sicherheitsfrage‘ (*):"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:38
|
||||
#, python-brace-format
|
||||
msgid "What is {question}?"
|
||||
msgstr "Wie viel ist {question}?"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:64
|
||||
msgid ""
|
||||
"A real bank should ask for a PIN/TAN instead of a simple calculation. For "
|
||||
"example by sending a one time password to the customer's mobile or providing "
|
||||
"her a random password generator."
|
||||
msgstr ""
|
||||
"Eine echte Bank würde an dieser Stelle die PIN der Konteninhaber abfragen, "
|
||||
"eine TAN an ein Mobilfunkgerät senden und diese TAN abfragen oder einen TAN-"
|
||||
"Generator verwenden lassen. Stattdessen gibt es hier diese kleine "
|
||||
"Rechenaufgabe."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:22
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr "In ein Taler-Wallet abheben"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:66
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Looks like your browser doesn't support GNU Taler payments. You can try "
|
||||
"installing a <a href=\"{wallet_link}\">wallet browser extension</a>."
|
||||
msgstr ""
|
||||
"Es sieht so aus, als würde Ihr Browser Zahlungen mit GNU Taler nicht "
|
||||
"unterstützen. Sie können jedoch alternativ eine <a href=\"{wallet_link"
|
||||
"}\">Browser-Erweiterung</a> installieren (wallet browser extension)."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:72
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr ""
|
||||
"Sie können diesen QR-Code verwenden, um in Ihr mobiles Wallet abzuheben:"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:77
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Click <a href=\"{taler_withdraw_uri}\">this link</a> to open your system's "
|
||||
"Taler wallet if it exists."
|
||||
msgstr ""
|
||||
"Klicken Sie <a href=\"{taler_withdraw_uri}\">diesen Link</a>, um das Wallet "
|
||||
"auf Ihrem System zu öffnen."
|
||||
|
||||
#: talerbank/app/views.py:353
|
||||
msgid "Bad form submitted!"
|
||||
msgstr ""
|
||||
"Es wurden fehlerhafte Daten oder ein unpassendes Datenformat übermittelt!"
|
||||
|
||||
#: talerbank/app/views.py:367
|
||||
msgid "Wire transfer successful!"
|
||||
msgstr "Überweisung erfolgreich ausgeführt!"
|
||||
|
||||
#: talerbank/app/views.py:520
|
||||
msgid "Registration successful!"
|
||||
msgstr "Registrierung erfolgreich!"
|
||||
|
||||
#: talerbank/app/views.py:1212
|
||||
msgid "Wrong CAPTCHA answer."
|
||||
msgstr "Die Captcha-Frage wurde leider nicht richtig beantwortet."
|
||||
|
||||
#: talerbank/app/views.py:1223
|
||||
msgid "Withdrawal successful!"
|
||||
msgstr "Abheben ins Wallet erfolgreich!"
|
|
@ -0,0 +1,279 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-20 13:09+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
#: talerbank/app/templates/404.html:23
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/404.html:30
|
||||
msgid "Page not found!"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/base.html:23
|
||||
#, python-brace-format
|
||||
msgid "{currency} Bank - Taler Demo"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/base.html:74
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"This part of the demo shows how a bank that supports Taler directly would "
|
||||
"work. In addition to using your own bank account, you can also see the "
|
||||
"transaction history of some <a href=\"{public_accounts}\">Public Accounts</"
|
||||
"a>."
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/base.html:80
|
||||
msgid "Introduction"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/base.html:81
|
||||
msgid "Bank"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/base.html:82
|
||||
msgid "Essay Shop"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/base.html:83
|
||||
msgid "Donations"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/base.html:84
|
||||
msgid "Tipping/Survey"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/base.html:94
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"You can learn more about Taler on our main <a href={taler_site}>website</a>."
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/login.html:22
|
||||
#, python-brace-format
|
||||
msgid "Welcome to the {currency} Bank!"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/login.html:29
|
||||
msgid "Please login!"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/login.html:33
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/login.html:40
|
||||
msgid ""
|
||||
"Your account doesn't have access to this page. To proceed, please login with "
|
||||
"an account that has access."
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/login.html:43
|
||||
msgid "Please login to see this page."
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/login.html:59
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"If you are a new customer please <a href=\"{register_link}\">register</a>. "
|
||||
"Registration is fast and free, and it gives you a registration bonus of 100 "
|
||||
"{currency}"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/login.html:63
|
||||
msgid "Registrations are not open to the public."
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/login.html:67
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"To view transactions of public accounts, please <a href="
|
||||
"\"{public_accounts}\">click here</a>."
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:23
|
||||
#: talerbank/app/templates/profile_page.html:28
|
||||
msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:30
|
||||
msgid "Wire transfer"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:31
|
||||
msgid "Transfer money via the payto system:"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:41
|
||||
msgid "payto address"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:45
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:25
|
||||
#, python-brace-format
|
||||
msgid "Welcome <em>{name}</em>!"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:33
|
||||
msgid "Bank account balance"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:51
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:58
|
||||
msgid "Amount to withdraw"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:73
|
||||
msgid "Start withdrawal"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:78
|
||||
msgid "Wire money"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:81
|
||||
msgid "Transactions for"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:87
|
||||
#: talerbank/app/templates/public_accounts.html:59
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:88
|
||||
#: talerbank/app/templates/public_accounts.html:60
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:89
|
||||
#: talerbank/app/templates/public_accounts.html:61
|
||||
msgid "Counterpart"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:90
|
||||
#: talerbank/app/templates/public_accounts.html:62
|
||||
msgid "Subject"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:107
|
||||
msgid "cancelled"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:116
|
||||
msgid "No transactions made to/from this account"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:21
|
||||
msgid "History of public accounts"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:71
|
||||
msgid "account"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:101
|
||||
#, python-brace-format
|
||||
msgid "No history for account #{account_number} ({account_name}) yet"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/register.html:22
|
||||
#, python-brace-format
|
||||
msgid "Register to the {currency} bank!"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/register.html:30
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/register.html:39
|
||||
msgid ""
|
||||
"Sorry, this username is no longer available. Please choose another one!"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:23
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:34
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{currency} Bank needs to verify that you intend to withdraw <b>{amount}</b> "
|
||||
"from <b>{exchange}</b>. To prove that you are the account owner, please "
|
||||
"answer the following "security question" (*):"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:38
|
||||
#, python-brace-format
|
||||
msgid "What is {question}?"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:64
|
||||
msgid ""
|
||||
"A real bank should ask for a PIN/TAN instead of a simple calculation. For "
|
||||
"example by sending a one time password to the customer's mobile or providing "
|
||||
"her a random password generator."
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:22
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:66
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Looks like your browser doesn't support GNU Taler payments. You can try "
|
||||
"installing a <a href=\"{wallet_link}\">wallet browser extension</a>."
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:72
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:77
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Click <a href=\"{taler_withdraw_uri}\">this link</a> to open your system's "
|
||||
"Taler wallet if it exists."
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/views.py:353
|
||||
msgid "Bad form submitted!"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/views.py:367
|
||||
msgid "Wire transfer successful!"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/views.py:520
|
||||
msgid "Registration successful!"
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/views.py:1212
|
||||
msgid "Wrong CAPTCHA answer."
|
||||
msgstr ""
|
||||
|
||||
#: talerbank/app/views.py:1223
|
||||
msgid "Withdrawal successful!"
|
||||
msgstr ""
|
|
@ -0,0 +1,306 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-20 13:09+0000\n"
|
||||
"PO-Revision-Date: 2021-02-23 11:28+0000\n"
|
||||
"Last-Translator: Stefan <eintritt@hotmail.com>\n"
|
||||
"Language-Team: Spanish <http://weblate.taler.net/projects/gnu-taler/"
|
||||
"taler-bank/es/>\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.4.2\n"
|
||||
|
||||
#: talerbank/app/templates/404.html:23
|
||||
msgid "Error"
|
||||
msgstr "Error"
|
||||
|
||||
#: talerbank/app/templates/404.html:30
|
||||
msgid "Page not found!"
|
||||
msgstr "Página no encontrada!"
|
||||
|
||||
#: talerbank/app/templates/base.html:23
|
||||
#, python-brace-format
|
||||
msgid "{currency} Bank - Taler Demo"
|
||||
msgstr "{currency} Banco - Taler Demo"
|
||||
|
||||
#: talerbank/app/templates/base.html:74
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"This part of the demo shows how a bank that supports Taler directly would "
|
||||
"work. In addition to using your own bank account, you can also see the "
|
||||
"transaction history of some <a href=\"{public_accounts}\">Public Accounts</"
|
||||
"a>."
|
||||
msgstr ""
|
||||
"Esta parte de la demo muestra como un banco que soporta Taler funcionaría "
|
||||
"directamente . Además usando tu propia cuenta bancaria, puedes ver el "
|
||||
"historial de transacciones de algunas <a href=\"{public_accounts}\">cuentas "
|
||||
"Públicas</a>."
|
||||
|
||||
#: talerbank/app/templates/base.html:80
|
||||
msgid "Introduction"
|
||||
msgstr "Introducción"
|
||||
|
||||
#: talerbank/app/templates/base.html:81
|
||||
msgid "Bank"
|
||||
msgstr "Banco"
|
||||
|
||||
#: talerbank/app/templates/base.html:82
|
||||
msgid "Essay Shop"
|
||||
msgstr "Tienda de pruebas"
|
||||
|
||||
#: talerbank/app/templates/base.html:83
|
||||
msgid "Donations"
|
||||
msgstr "Donaciones"
|
||||
|
||||
#: talerbank/app/templates/base.html:84
|
||||
msgid "Tipping/Survey"
|
||||
msgstr "Consejos/Encuestas"
|
||||
|
||||
#: talerbank/app/templates/base.html:94
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"You can learn more about Taler on our main <a href={taler_site}>website</a>."
|
||||
msgstr ""
|
||||
"Puedes aprender más sobre Taler en nuestra <a href={taler_site}>página Web</"
|
||||
"a> principal."
|
||||
|
||||
#: talerbank/app/templates/login.html:22
|
||||
#, python-brace-format
|
||||
msgid "Welcome to the {currency} Bank!"
|
||||
msgstr "Bienvenido al banco de {currency}!"
|
||||
|
||||
#: talerbank/app/templates/login.html:29
|
||||
msgid "Please login!"
|
||||
msgstr "Por favor inicia sesión!"
|
||||
|
||||
#: talerbank/app/templates/login.html:33
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr "Tu usuario y contraseña no coinciden. Por favor prueba de nuevo."
|
||||
|
||||
#: talerbank/app/templates/login.html:40
|
||||
msgid ""
|
||||
"Your account doesn't have access to this page. To proceed, please login with "
|
||||
"an account that has access."
|
||||
msgstr ""
|
||||
"Tu cuenta no tiene acceso a esta página. Para proceder, por favor inicia "
|
||||
"sesión con una cuenta que tenga acceso."
|
||||
|
||||
#: talerbank/app/templates/login.html:43
|
||||
msgid "Please login to see this page."
|
||||
msgstr "Por favor inicia sesión para ver esta página."
|
||||
|
||||
#: talerbank/app/templates/login.html:59
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"If you are a new customer please <a href=\"{register_link}\">register</a>. "
|
||||
"Registration is fast and free, and it gives you a registration bonus of 100 "
|
||||
"{currency}"
|
||||
msgstr ""
|
||||
"Si tu eres un nuevo cliente por favor <a href=\"{register_link}\""
|
||||
">regístrate</a>. El registro es rápido y gratuito, y te da un bono de "
|
||||
"registro de 100 {currency}"
|
||||
|
||||
#: talerbank/app/templates/login.html:63
|
||||
msgid "Registrations are not open to the public."
|
||||
msgstr "Las inscripciones no están abiertas al público."
|
||||
|
||||
#: talerbank/app/templates/login.html:67
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"To view transactions of public accounts, please <a href="
|
||||
"\"{public_accounts}\">click here</a>."
|
||||
msgstr ""
|
||||
"Para ver transacciones de cuentas públicas, por favor <a href=\""
|
||||
"{public_accounts}\">haz click aquí</a>."
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:23
|
||||
#: talerbank/app/templates/profile_page.html:28
|
||||
msgid "Logout"
|
||||
msgstr "Cierre de sesión"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:30
|
||||
msgid "Wire transfer"
|
||||
msgstr "Transferencia bancaria"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:31
|
||||
msgid "Transfer money via the payto system:"
|
||||
msgstr "Transferir dinero a través del sistema payto:"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:41
|
||||
msgid "payto address"
|
||||
msgstr "dirección payto"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:45
|
||||
msgid "Confirm"
|
||||
msgstr "Confirmar"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:25
|
||||
#, python-brace-format
|
||||
msgid "Welcome <em>{name}</em>!"
|
||||
msgstr "Bienvenido <em>{name}</em>!"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:33
|
||||
msgid "Bank account balance"
|
||||
msgstr "Balance de cuenta bancaria"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:51
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr "Retirar dinero hacia una cartera Taler"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:58
|
||||
msgid "Amount to withdraw"
|
||||
msgstr "Cantidad a retirar"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:73
|
||||
msgid "Start withdrawal"
|
||||
msgstr "Comenzar la retirada"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:78
|
||||
msgid "Wire money"
|
||||
msgstr "Transferir dinero"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:81
|
||||
msgid "Transactions for"
|
||||
msgstr "Transacciones para"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:87
|
||||
#: talerbank/app/templates/public_accounts.html:59
|
||||
msgid "Date"
|
||||
msgstr "Fecha"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:88
|
||||
#: talerbank/app/templates/public_accounts.html:60
|
||||
msgid "Amount"
|
||||
msgstr "Cantidad"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:89
|
||||
#: talerbank/app/templates/public_accounts.html:61
|
||||
msgid "Counterpart"
|
||||
msgstr "Contraparte"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:90
|
||||
#: talerbank/app/templates/public_accounts.html:62
|
||||
msgid "Subject"
|
||||
msgstr "Asunto"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:107
|
||||
msgid "cancelled"
|
||||
msgstr "cancelada"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:116
|
||||
msgid "No transactions made to/from this account"
|
||||
msgstr "Ninguna transacción realizada a/desde esta cuenta"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:21
|
||||
msgid "History of public accounts"
|
||||
msgstr "Historial de cuentas públicas"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:71
|
||||
msgid "account"
|
||||
msgstr "cuenta"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:101
|
||||
#, python-brace-format
|
||||
msgid "No history for account #{account_number} ({account_name}) yet"
|
||||
msgstr "Sin historia para la cuenta #{account_number} ({account_name}) todavía"
|
||||
|
||||
#: talerbank/app/templates/register.html:22
|
||||
#, python-brace-format
|
||||
msgid "Register to the {currency} bank!"
|
||||
msgstr "Registro en el banco de {currency} !"
|
||||
|
||||
#: talerbank/app/templates/register.html:30
|
||||
msgid "Back"
|
||||
msgstr "Atrás"
|
||||
|
||||
#: talerbank/app/templates/register.html:39
|
||||
msgid ""
|
||||
"Sorry, this username is no longer available. Please choose another one!"
|
||||
msgstr ""
|
||||
"Disculpa, el nombre de usuario ya no está disponible. Por favor elige otro!"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:23
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr "Confirmar retirada"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:34
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{currency} Bank needs to verify that you intend to withdraw <b>{amount}</b> "
|
||||
"from <b>{exchange}</b>. To prove that you are the account owner, please "
|
||||
"answer the following "security question" (*):"
|
||||
msgstr ""
|
||||
"{currency} El banco necesita verificar que tú intentas retirar la cantidad "
|
||||
"de <b>{amount}</b> desde <b>{exchange}</b>.Para comprobar que tú eres el "
|
||||
"propietario de la cuenta , por favor contesta la siguiente "pregunta de "
|
||||
"seguridad " (*):"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:38
|
||||
#, python-brace-format
|
||||
msgid "What is {question}?"
|
||||
msgstr "Qué es {question}?"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:64
|
||||
msgid ""
|
||||
"A real bank should ask for a PIN/TAN instead of a simple calculation. For "
|
||||
"example by sending a one time password to the customer's mobile or providing "
|
||||
"her a random password generator."
|
||||
msgstr ""
|
||||
"Un banco real debe solicitar un PIN/TAN en vez de un simple cálculo. Por "
|
||||
"ejemplo mandando una contraseña de un solo uso al teléfono móvil del cliente "
|
||||
"o proveyéndole de un generador de contraseñas aleatorio."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:22
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr "Retirar hacia la cartera Taler"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:66
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Looks like your browser doesn't support GNU Taler payments. You can try "
|
||||
"installing a <a href=\"{wallet_link}\">wallet browser extension</a>."
|
||||
msgstr ""
|
||||
"Parece ser que tu navegador no soporta los pagos GNU Taler. Puedes probar a "
|
||||
"instalar <a href=\"{wallet_link}\">un complemento para navegador</a>."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:72
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr "Puedes usar este código QR para retirar a la cartera de tu móvil:"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:77
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Click <a href=\"{taler_withdraw_uri}\">this link</a> to open your system's "
|
||||
"Taler wallet if it exists."
|
||||
msgstr ""
|
||||
"Haz clic en <a href=\"{taler_withdraw_uri}\">este enlace</a> para abrir la "
|
||||
"cartera Taler de tu sistema si esta existe."
|
||||
|
||||
#: talerbank/app/views.py:353
|
||||
msgid "Bad form submitted!"
|
||||
msgstr "Formulario erróneo enviado!"
|
||||
|
||||
#: talerbank/app/views.py:367
|
||||
msgid "Wire transfer successful!"
|
||||
msgstr "Transferencia bancaria realizada con éxito!"
|
||||
|
||||
#: talerbank/app/views.py:520
|
||||
msgid "Registration successful!"
|
||||
msgstr "Registro realizado con éxito!"
|
||||
|
||||
#: talerbank/app/views.py:1212
|
||||
msgid "Wrong CAPTCHA answer."
|
||||
msgstr "Respuesta CAPTCHA errónea."
|
||||
|
||||
#: talerbank/app/views.py:1223
|
||||
msgid "Withdrawal successful!"
|
||||
msgstr "Retirada realizada con éxito!"
|
|
@ -0,0 +1,311 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-20 13:09+0000\n"
|
||||
"PO-Revision-Date: 2021-03-17 18:31+0000\n"
|
||||
"Last-Translator: Marianne Le Guennec <marianne.leguennec@gmail.com>\n"
|
||||
"Language-Team: French <http://weblate.taler.net/projects/gnu-taler/"
|
||||
"taler-bank/fr/>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.4.2\n"
|
||||
|
||||
#: talerbank/app/templates/404.html:23
|
||||
msgid "Error"
|
||||
msgstr "Erreur"
|
||||
|
||||
#: talerbank/app/templates/404.html:30
|
||||
msgid "Page not found!"
|
||||
msgstr "Page introuvable !"
|
||||
|
||||
#: talerbank/app/templates/base.html:23
|
||||
#, python-brace-format
|
||||
msgid "{currency} Bank - Taler Demo"
|
||||
msgstr "{currency} Banque - Taler Démo"
|
||||
|
||||
#: talerbank/app/templates/base.html:74
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"This part of the demo shows how a bank that supports Taler directly would "
|
||||
"work. In addition to using your own bank account, you can also see the "
|
||||
"transaction history of some <a href=\"{public_accounts}\">Public Accounts</"
|
||||
"a>."
|
||||
msgstr ""
|
||||
"Cette section de démo vous montre comment fonctionnerait une banque qui "
|
||||
"soutiendrait directement Taler. En plus de passer par votre propre compte "
|
||||
"bancaire, vous avez accès à l'historique des transactions de certains <a "
|
||||
"href=\"{public_accounts}\">Comptes Publiques</a>."
|
||||
|
||||
#: talerbank/app/templates/base.html:80
|
||||
msgid "Introduction"
|
||||
msgstr "Introduction"
|
||||
|
||||
#: talerbank/app/templates/base.html:81
|
||||
msgid "Bank"
|
||||
msgstr "Banque"
|
||||
|
||||
#: talerbank/app/templates/base.html:82
|
||||
msgid "Essay Shop"
|
||||
msgstr "Boutique de test"
|
||||
|
||||
#: talerbank/app/templates/base.html:83
|
||||
msgid "Donations"
|
||||
msgstr "Dons"
|
||||
|
||||
#: talerbank/app/templates/base.html:84
|
||||
msgid "Tipping/Survey"
|
||||
msgstr "Conseils/Sondage"
|
||||
|
||||
#: talerbank/app/templates/base.html:94
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"You can learn more about Taler on our main <a href={taler_site}>website</a>."
|
||||
msgstr ""
|
||||
"Pour en savoir plus sur Taler, vous pouvez consulter notre <a "
|
||||
"href={taler_site}>site</a> principal."
|
||||
|
||||
#: talerbank/app/templates/login.html:22
|
||||
#, python-brace-format
|
||||
msgid "Welcome to the {currency} Bank!"
|
||||
msgstr "Bienvenue dans votre Banque {currency} !"
|
||||
|
||||
#: talerbank/app/templates/login.html:29
|
||||
msgid "Please login!"
|
||||
msgstr "Veuillez vous identifier !"
|
||||
|
||||
#: talerbank/app/templates/login.html:33
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr ""
|
||||
"Une erreur s'est produite avec votre nom d'utilisateur ou votre mot de "
|
||||
"passe. Veuillez réessayer."
|
||||
|
||||
#: talerbank/app/templates/login.html:40
|
||||
msgid ""
|
||||
"Your account doesn't have access to this page. To proceed, please login with "
|
||||
"an account that has access."
|
||||
msgstr ""
|
||||
"Vous n'avez pas accès à cette page depuis votre compte. Afin de poursuivre, "
|
||||
"veuillez vous connecter depuis un compte y permettant l'accès."
|
||||
|
||||
#: talerbank/app/templates/login.html:43
|
||||
msgid "Please login to see this page."
|
||||
msgstr "Veuillez vous identifier pour accéder à cette page."
|
||||
|
||||
#: talerbank/app/templates/login.html:59
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"If you are a new customer please <a href=\"{register_link}\">register</a>. "
|
||||
"Registration is fast and free, and it gives you a registration bonus of 100 "
|
||||
"{currency}"
|
||||
msgstr ""
|
||||
"Si vous êtes un nouvel utilisateur, veuillez vous <a href=\"{register_link}\""
|
||||
">inscrire</a>. L'inscription est rapide et gratuite. Vous bénéficiez d'un "
|
||||
"bonus de 100 {currency} à l'inscription."
|
||||
|
||||
#: talerbank/app/templates/login.html:63
|
||||
msgid "Registrations are not open to the public."
|
||||
msgstr "Les inscriptions ne sont pas ouvertes au public."
|
||||
|
||||
#: talerbank/app/templates/login.html:67
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"To view transactions of public accounts, please <a href="
|
||||
"\"{public_accounts}\">click here</a>."
|
||||
msgstr ""
|
||||
"Pour accéder aux transactions de comptes publics, <a href=\"{public_accounts}"
|
||||
"\">cliquez ici</a>."
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:23
|
||||
#: talerbank/app/templates/profile_page.html:28
|
||||
msgid "Logout"
|
||||
msgstr "Déconnexion"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:30
|
||||
msgid "Wire transfer"
|
||||
msgstr "Virement bancaire"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:31
|
||||
msgid "Transfer money via the payto system:"
|
||||
msgstr "Virer de l'argent via le système payto :"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:41
|
||||
msgid "payto address"
|
||||
msgstr "Adresse payto"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:45
|
||||
msgid "Confirm"
|
||||
msgstr "Confirmer"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:25
|
||||
#, python-brace-format
|
||||
msgid "Welcome <em>{name}</em>!"
|
||||
msgstr "Bienvenue <em>{name}</em> !"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:33
|
||||
msgid "Bank account balance"
|
||||
msgstr "Solde du compte bancaire"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:51
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr "Retirer de l'argent dans un portefeuille Taler"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:58
|
||||
msgid "Amount to withdraw"
|
||||
msgstr "Montant à retirer"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:73
|
||||
msgid "Start withdrawal"
|
||||
msgstr "Retrait initial"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:78
|
||||
msgid "Wire money"
|
||||
msgstr "Virement bancaire"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:81
|
||||
msgid "Transactions for"
|
||||
msgstr "Transactions pour"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:87
|
||||
#: talerbank/app/templates/public_accounts.html:59
|
||||
msgid "Date"
|
||||
msgstr "Date"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:88
|
||||
#: talerbank/app/templates/public_accounts.html:60
|
||||
msgid "Amount"
|
||||
msgstr "Montant"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:89
|
||||
#: talerbank/app/templates/public_accounts.html:61
|
||||
msgid "Counterpart"
|
||||
msgstr "Contrepartie"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:90
|
||||
#: talerbank/app/templates/public_accounts.html:62
|
||||
msgid "Subject"
|
||||
msgstr "Sujet"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:107
|
||||
msgid "cancelled"
|
||||
msgstr "Annulé"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:116
|
||||
msgid "No transactions made to/from this account"
|
||||
msgstr "Aucune transaction effectuée vers/depuis ce compte"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:21
|
||||
msgid "History of public accounts"
|
||||
msgstr "Historique de comptes publiques"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:71
|
||||
msgid "account"
|
||||
msgstr "compte"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:101
|
||||
#, python-brace-format
|
||||
msgid "No history for account #{account_number} ({account_name}) yet"
|
||||
msgstr ""
|
||||
"Aucun historique pour le compte #{account_number} ({account_name}) pour "
|
||||
"l'instant"
|
||||
|
||||
#: talerbank/app/templates/register.html:22
|
||||
#, python-brace-format
|
||||
msgid "Register to the {currency} bank!"
|
||||
msgstr "Inscrivez-vous à la banque {currency} !"
|
||||
|
||||
#: talerbank/app/templates/register.html:30
|
||||
msgid "Back"
|
||||
msgstr "Retour"
|
||||
|
||||
#: talerbank/app/templates/register.html:39
|
||||
msgid ""
|
||||
"Sorry, this username is no longer available. Please choose another one!"
|
||||
msgstr "Désolé, ce nom d'utilisateur est déjà pris. Choisissez-en un autre !"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:23
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr "Confirmer le retrait"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:34
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{currency} Bank needs to verify that you intend to withdraw <b>{amount}</b> "
|
||||
"from <b>{exchange}</b>. To prove that you are the account owner, please "
|
||||
"answer the following "security question" (*):"
|
||||
msgstr ""
|
||||
"La banque {currency} a besoin de vérifier que vous avez l'intention de "
|
||||
"retirer <b>{amount}</b> de <b>{exchange}</b> . Pour prouver que vous êtes le "
|
||||
"propriétaire du compte, veuillez répondre aux " questions de sécurité "
|
||||
"" suivantes (*) :"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:38
|
||||
#, python-brace-format
|
||||
msgid "What is {question}?"
|
||||
msgstr "Qu'est-ce que {question} ?"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:64
|
||||
msgid ""
|
||||
"A real bank should ask for a PIN/TAN instead of a simple calculation. For "
|
||||
"example by sending a one time password to the customer's mobile or providing "
|
||||
"her a random password generator."
|
||||
msgstr ""
|
||||
"Une vraie banque devrait demander un PIN/TAN au lieu d'un simple chiffrage. "
|
||||
"En envoyant, par example, un mot de passe à usage unique au téléphone du "
|
||||
"client ou de fournir un générateur de mot de passe aléatoire."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:22
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr "Retirer vers un portefeuille Taler"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:66
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Looks like your browser doesn't support GNU Taler payments. You can try "
|
||||
"installing a <a href=\"{wallet_link}\">wallet browser extension</a>."
|
||||
msgstr ""
|
||||
"Il semblerait que votre navigateur ne soit pas compatible avec les paiements "
|
||||
"GNU Taler. Vous pouvez essayer d'installer un <a href=\"{wallet_link}\""
|
||||
">portefeuille en extension du navigateur</a> ."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:72
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr ""
|
||||
"Vous pouvez utiliser ce QR Code pour retirer vers votre portefeuille mobile :"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:77
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Click <a href=\"{taler_withdraw_uri}\">this link</a> to open your system's "
|
||||
"Taler wallet if it exists."
|
||||
msgstr ""
|
||||
"Cliquez sur <a href=\"{taler_withdraw_uri}\">ce lien</a> pour ouvrir votre "
|
||||
"portefeuille Taler, s'il existe."
|
||||
|
||||
#: talerbank/app/views.py:353
|
||||
msgid "Bad form submitted!"
|
||||
msgstr "Mauvais formulaire soumit !"
|
||||
|
||||
#: talerbank/app/views.py:367
|
||||
msgid "Wire transfer successful!"
|
||||
msgstr "Virement bancaire réussi !"
|
||||
|
||||
#: talerbank/app/views.py:520
|
||||
msgid "Registration successful!"
|
||||
msgstr "Inscription réussie !"
|
||||
|
||||
#: talerbank/app/views.py:1212
|
||||
msgid "Wrong CAPTCHA answer."
|
||||
msgstr "CAPTCHA erroné ."
|
||||
|
||||
#: talerbank/app/views.py:1223
|
||||
msgid "Withdrawal successful!"
|
||||
msgstr "Retrait réussi !"
|
|
@ -0,0 +1,307 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-20 13:09+0000\n"
|
||||
"PO-Revision-Date: 2021-02-24 16:13+0000\n"
|
||||
"Last-Translator: MS <ms@taler.net>\n"
|
||||
"Language-Team: Italian <http://weblate.taler.net/projects/gnu-taler/"
|
||||
"taler-bank/it/>\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.4.2\n"
|
||||
|
||||
#: talerbank/app/templates/404.html:23
|
||||
msgid "Error"
|
||||
msgstr "Errore"
|
||||
|
||||
#: talerbank/app/templates/404.html:30
|
||||
msgid "Page not found!"
|
||||
msgstr "Pagina non trovata!"
|
||||
|
||||
#: talerbank/app/templates/base.html:23
|
||||
#, python-brace-format
|
||||
msgid "{currency} Bank - Taler Demo"
|
||||
msgstr "Banca {currency} - Taler Demo"
|
||||
|
||||
#: talerbank/app/templates/base.html:74
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"This part of the demo shows how a bank that supports Taler directly would "
|
||||
"work. In addition to using your own bank account, you can also see the "
|
||||
"transaction history of some <a href=\"{public_accounts}\">Public Accounts</"
|
||||
"a>."
|
||||
msgstr ""
|
||||
"Questa parte della demo mostra come dovrebbe funzionare una banca che "
|
||||
"supporti appieno il protocollo Taler. Oltre al tuo conto personale, è "
|
||||
"possibile visualizzare lo storico di alcuni <a href=\"{public_accounts}\""
|
||||
">conti pubblici</a>"
|
||||
|
||||
#: talerbank/app/templates/base.html:80
|
||||
msgid "Introduction"
|
||||
msgstr "Introduzione"
|
||||
|
||||
#: talerbank/app/templates/base.html:81
|
||||
msgid "Bank"
|
||||
msgstr "Banca"
|
||||
|
||||
#: talerbank/app/templates/base.html:82
|
||||
msgid "Essay Shop"
|
||||
msgstr "Negozio di saggistica"
|
||||
|
||||
#: talerbank/app/templates/base.html:83
|
||||
msgid "Donations"
|
||||
msgstr "Donazioni"
|
||||
|
||||
#: talerbank/app/templates/base.html:84
|
||||
msgid "Tipping/Survey"
|
||||
msgstr "Guadagna con il questionario"
|
||||
|
||||
#: talerbank/app/templates/base.html:94
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"You can learn more about Taler on our main <a href={taler_site}>website</a>."
|
||||
msgstr ""
|
||||
"Per maggiori informazioni su Taler, visita il nostro <a href={taler_site}"
|
||||
">sito</a> "
|
||||
|
||||
#: talerbank/app/templates/login.html:22
|
||||
#, python-brace-format
|
||||
msgid "Welcome to the {currency} Bank!"
|
||||
msgstr "Benvenuti nella Banca {currency}"
|
||||
|
||||
#: talerbank/app/templates/login.html:29
|
||||
msgid "Please login!"
|
||||
msgstr "Accedi!"
|
||||
|
||||
#: talerbank/app/templates/login.html:33
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr "Il tuo nome utente e password sono incorretti. Prova di nuovo."
|
||||
|
||||
#: talerbank/app/templates/login.html:40
|
||||
msgid ""
|
||||
"Your account doesn't have access to this page. To proceed, please login with "
|
||||
"an account that has access."
|
||||
msgstr ""
|
||||
"Il tuo profilo non ha accesso a questa pagina. Per continuare, ti invitiamo "
|
||||
"ad effettuare l'accesso con un profilo che abbia i diritti necessari."
|
||||
|
||||
#: talerbank/app/templates/login.html:43
|
||||
msgid "Please login to see this page."
|
||||
msgstr "Effettua l'accesso per vedere questa pagina."
|
||||
|
||||
#: talerbank/app/templates/login.html:59
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"If you are a new customer please <a href=\"{register_link}\">register</a>. "
|
||||
"Registration is fast and free, and it gives you a registration bonus of 100 "
|
||||
"{currency}"
|
||||
msgstr ""
|
||||
"Per diventare nuovo cliente, <a href=\"{register_link}\">clicca qui</a>. La "
|
||||
"registrazione è facile e veloce, e ti regala un bonus di 100 {currency}"
|
||||
|
||||
#: talerbank/app/templates/login.html:63
|
||||
msgid "Registrations are not open to the public."
|
||||
msgstr "Le registrazioni sono al momento disabilitate"
|
||||
|
||||
#: talerbank/app/templates/login.html:67
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"To view transactions of public accounts, please <a href="
|
||||
"\"{public_accounts}\">click here</a>."
|
||||
msgstr ""
|
||||
"Clicca <a href=\"{public_accounts}\">qui</a> per visualizzare le transazioni "
|
||||
"dei conti pubblici"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:23
|
||||
#: talerbank/app/templates/profile_page.html:28
|
||||
msgid "Logout"
|
||||
msgstr "Esci"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:30
|
||||
msgid "Wire transfer"
|
||||
msgstr "Effettua un bonifico"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:31
|
||||
msgid "Transfer money via the payto system:"
|
||||
msgstr "Effettua un bonifico usando il sistema 'payto':"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:41
|
||||
msgid "payto address"
|
||||
msgstr "indirizzo 'payto'"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:45
|
||||
msgid "Confirm"
|
||||
msgstr "Conferma"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:25
|
||||
#, python-brace-format
|
||||
msgid "Welcome <em>{name}</em>!"
|
||||
msgstr "Benvenut* <em>{name}</em>!"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:33
|
||||
msgid "Bank account balance"
|
||||
msgstr "Bilancio"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:51
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr "Ricarica il tuo portafoglio Taler"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:58
|
||||
msgid "Amount to withdraw"
|
||||
msgstr "Cifra da ritirare"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:73
|
||||
msgid "Start withdrawal"
|
||||
msgstr "Invia la richiesta"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:78
|
||||
msgid "Wire money"
|
||||
msgstr "Effettua un bonifico"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:81
|
||||
msgid "Transactions for"
|
||||
msgstr "Storico di"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:87
|
||||
#: talerbank/app/templates/public_accounts.html:59
|
||||
msgid "Date"
|
||||
msgstr "Data"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:88
|
||||
#: talerbank/app/templates/public_accounts.html:60
|
||||
msgid "Amount"
|
||||
msgstr "Cifra"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:89
|
||||
#: talerbank/app/templates/public_accounts.html:61
|
||||
msgid "Counterpart"
|
||||
msgstr "Controparte"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:90
|
||||
#: talerbank/app/templates/public_accounts.html:62
|
||||
msgid "Subject"
|
||||
msgstr "Causale"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:107
|
||||
msgid "cancelled"
|
||||
msgstr "annullato"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:116
|
||||
msgid "No transactions made to/from this account"
|
||||
msgstr "Nessuna transazione effettuata"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:21
|
||||
msgid "History of public accounts"
|
||||
msgstr "Storico dei conti pubblici"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:71
|
||||
msgid "account"
|
||||
msgstr "conto"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:101
|
||||
#, python-brace-format
|
||||
msgid "No history for account #{account_number} ({account_name}) yet"
|
||||
msgstr ""
|
||||
"Ancora nessuno storico relativo al conto {account_number} ({account_name})"
|
||||
|
||||
#: talerbank/app/templates/register.html:22
|
||||
#, python-brace-format
|
||||
msgid "Register to the {currency} bank!"
|
||||
msgstr "Apri un conto presso la banca {currency}!"
|
||||
|
||||
#: talerbank/app/templates/register.html:30
|
||||
msgid "Back"
|
||||
msgstr "Indietro"
|
||||
|
||||
#: talerbank/app/templates/register.html:39
|
||||
msgid ""
|
||||
"Sorry, this username is no longer available. Please choose another one!"
|
||||
msgstr ""
|
||||
"Ci dispiace, ma il nome utente scelto non è al momento disponibile. Prova "
|
||||
"con un altro!"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:23
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr "Conferma la richiesta"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:34
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{currency} Bank needs to verify that you intend to withdraw <b>{amount}</b> "
|
||||
"from <b>{exchange}</b>. To prove that you are the account owner, please "
|
||||
"answer the following "security question" (*):"
|
||||
msgstr ""
|
||||
"La banca {currency} deve verificare che tu intendi ritirare <b>{amount}</b> "
|
||||
"da <b>{exchange}</b>. Per dimostrare che il proprietario del conto corrente "
|
||||
"sia tu, ti preghiamo di rispondere alla seguente "domanda di "
|
||||
"sicurezza" (*):"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:38
|
||||
#, python-brace-format
|
||||
msgid "What is {question}?"
|
||||
msgstr "Indica il risultato di {question}:"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:64
|
||||
msgid ""
|
||||
"A real bank should ask for a PIN/TAN instead of a simple calculation. For "
|
||||
"example by sending a one time password to the customer's mobile or providing "
|
||||
"her a random password generator."
|
||||
msgstr ""
|
||||
"Una banca vera dovrebbe comunicare un PIN aggiuntivo come misura di "
|
||||
"sicurezza, invece di un semplice calcolo come avviene in questa pagina."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:22
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr "Ricarica il tuo portafoglio Taler"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:66
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Looks like your browser doesn't support GNU Taler payments. You can try "
|
||||
"installing a <a href=\"{wallet_link}\">wallet browser extension</a>."
|
||||
msgstr ""
|
||||
"Sembra che il tuo browser non supporti i pagamenti Taler, prova ad "
|
||||
"installare il <a href=\"{wallet_link}\">portafoglio</a>."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:72
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr "Usa questo QR-code per ricaricare il tuo portafoglio:"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:77
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Click <a href=\"{taler_withdraw_uri}\">this link</a> to open your system's "
|
||||
"Taler wallet if it exists."
|
||||
msgstr ""
|
||||
"Clicca <a href=\"{taler_withdraw_uri}\">qui</a> per accedere al tuo "
|
||||
"portafoglio."
|
||||
|
||||
#: talerbank/app/views.py:353
|
||||
msgid "Bad form submitted!"
|
||||
msgstr "La richiesta effettuata non è valida."
|
||||
|
||||
#: talerbank/app/views.py:367
|
||||
#| msgid "Wire transfer"
|
||||
msgid "Wire transfer successful!"
|
||||
msgstr "Bonifico effettuato con successo!"
|
||||
|
||||
#: talerbank/app/views.py:520
|
||||
msgid "Registration successful!"
|
||||
msgstr "Registrazione avvenuta con successo!"
|
||||
|
||||
#: talerbank/app/views.py:1212
|
||||
msgid "Wrong CAPTCHA answer."
|
||||
msgstr "La risposta è incorretta."
|
||||
|
||||
#: talerbank/app/views.py:1223
|
||||
msgid "Withdrawal successful!"
|
||||
msgstr "Ricarica effettuata con successo!"
|
|
@ -0,0 +1,291 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-20 13:09+0000\n"
|
||||
"PO-Revision-Date: 2021-03-15 15:11+0000\n"
|
||||
"Last-Translator: Miyuki Komatsu <miykom@gmail.com>\n"
|
||||
"Language-Team: Japanese <http://weblate.taler.net/projects/gnu-taler/"
|
||||
"taler-bank/ja/>\n"
|
||||
"Language: ja\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 4.4.2\n"
|
||||
|
||||
#: talerbank/app/templates/404.html:23
|
||||
msgid "Error"
|
||||
msgstr "エラー"
|
||||
|
||||
#: talerbank/app/templates/404.html:30
|
||||
msgid "Page not found!"
|
||||
msgstr "ページが見つかりません!"
|
||||
|
||||
#: talerbank/app/templates/base.html:23
|
||||
#, python-brace-format
|
||||
msgid "{currency} Bank - Taler Demo"
|
||||
msgstr "{currency} 銀行 - Talerデモ"
|
||||
|
||||
#: talerbank/app/templates/base.html:74
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"This part of the demo shows how a bank that supports Taler directly would "
|
||||
"work. In addition to using your own bank account, you can also see the "
|
||||
"transaction history of some <a href=\"{public_accounts}\">Public Accounts</"
|
||||
"a>."
|
||||
msgstr ""
|
||||
"デモのこの部分は、Talerを直接サポートしている銀行がどのように動作するかを示しています。自分の銀行口座を使うだけでなく、いくつかの <a href="
|
||||
"\"{public_accounts}\">パブリックアカウント</a> の取引履歴を見ることもできます。"
|
||||
|
||||
#: talerbank/app/templates/base.html:80
|
||||
msgid "Introduction"
|
||||
msgstr "序章"
|
||||
|
||||
#: talerbank/app/templates/base.html:81
|
||||
msgid "Bank"
|
||||
msgstr "銀行"
|
||||
|
||||
#: talerbank/app/templates/base.html:82
|
||||
msgid "Essay Shop"
|
||||
msgstr "エッセイショップ"
|
||||
|
||||
#: talerbank/app/templates/base.html:83
|
||||
msgid "Donations"
|
||||
msgstr "寄付"
|
||||
|
||||
#: talerbank/app/templates/base.html:84
|
||||
msgid "Tipping/Survey"
|
||||
msgstr "チップ/調査"
|
||||
|
||||
#: talerbank/app/templates/base.html:94
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"You can learn more about Taler on our main <a href={taler_site}>website</a>."
|
||||
msgstr "Talerの詳細については、メインの<a href={taler_site}>Webサイトをご覧ください</a>。"
|
||||
|
||||
#: talerbank/app/templates/login.html:22
|
||||
#, python-brace-format
|
||||
msgid "Welcome to the {currency} Bank!"
|
||||
msgstr "{currency}銀行へようこそ!"
|
||||
|
||||
#: talerbank/app/templates/login.html:29
|
||||
msgid "Please login!"
|
||||
msgstr "ログイン してください!"
|
||||
|
||||
#: talerbank/app/templates/login.html:33
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr "ユーザー名とパスワードが一致していません."
|
||||
|
||||
#: talerbank/app/templates/login.html:40
|
||||
msgid ""
|
||||
"Your account doesn't have access to this page. To proceed, please login with "
|
||||
"an account that has access."
|
||||
msgstr "あなたのアカウントにはこのページへのアクセス権がありません。先に進むには、アクセスできるアカウントでログインしてください。"
|
||||
|
||||
#: talerbank/app/templates/login.html:43
|
||||
msgid "Please login to see this page."
|
||||
msgstr "このページを表示するにはログインしてください。"
|
||||
|
||||
#: talerbank/app/templates/login.html:59
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"If you are a new customer please <a href=\"{register_link}\">register</a>. "
|
||||
"Registration is fast and free, and it gives you a registration bonus of 100 "
|
||||
"{currency}"
|
||||
msgstr ""
|
||||
"あなたが新しい顧客である場合は、<a href=\"{register_link}\">登録してください</a>。"
|
||||
"登録は迅速かつ無料で,それはあなたに100 {currency}の登録ボーナスを与えます"
|
||||
|
||||
#: talerbank/app/templates/login.html:63
|
||||
msgid "Registrations are not open to the public."
|
||||
msgstr "登録は一般に公開されていません。"
|
||||
|
||||
#: talerbank/app/templates/login.html:67
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"To view transactions of public accounts, please <a href="
|
||||
"\"{public_accounts}\">click here</a>."
|
||||
msgstr "パブリックアカウントの取引を表示するには、<a href=\"{public_accounts}\">ここをクリックしてください</a>。"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:23
|
||||
#: talerbank/app/templates/profile_page.html:28
|
||||
msgid "Logout"
|
||||
msgstr "ログアウト"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:30
|
||||
msgid "Wire transfer"
|
||||
msgstr "電信送金"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:31
|
||||
msgid "Transfer money via the payto system:"
|
||||
msgstr "Paytoシステムを介して送金します。"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:41
|
||||
msgid "payto address"
|
||||
msgstr "ペイトアドレス"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:45
|
||||
msgid "Confirm"
|
||||
msgstr "確認"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:25
|
||||
#, python-brace-format
|
||||
msgid "Welcome <em>{name}</em>!"
|
||||
msgstr "ようこそ<em>{name}</em> !"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:33
|
||||
msgid "Bank account balance"
|
||||
msgstr "銀行口座残高"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:51
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr "ターラーウォレットにお金を引き出す"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:58
|
||||
msgid "Amount to withdraw"
|
||||
msgstr "引き出し額"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:73
|
||||
msgid "Start withdrawal"
|
||||
msgstr "引き出しを開始する"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:78
|
||||
msgid "Wire money"
|
||||
msgstr "ワイヤーマネー"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:81
|
||||
msgid "Transactions for"
|
||||
msgstr "のトランザクション"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:87
|
||||
#: talerbank/app/templates/public_accounts.html:59
|
||||
msgid "Date"
|
||||
msgstr "日付"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:88
|
||||
#: talerbank/app/templates/public_accounts.html:60
|
||||
msgid "Amount"
|
||||
msgstr "合計"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:89
|
||||
#: talerbank/app/templates/public_accounts.html:61
|
||||
msgid "Counterpart"
|
||||
msgstr "カウンターパート"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:90
|
||||
#: talerbank/app/templates/public_accounts.html:62
|
||||
msgid "Subject"
|
||||
msgstr "題名"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:107
|
||||
msgid "cancelled"
|
||||
msgstr "キャンセル"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:116
|
||||
msgid "No transactions made to/from this account"
|
||||
msgstr "このアカウントとの間で行われたトランザクションはありません"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:21
|
||||
msgid "History of public accounts"
|
||||
msgstr "公会計の歴史"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:71
|
||||
msgid "account"
|
||||
msgstr "アカウント"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:101
|
||||
#, python-brace-format
|
||||
msgid "No history for account #{account_number} ({account_name}) yet"
|
||||
msgstr "アカウント#{account_number}({account_name})の履歴はまだありません"
|
||||
|
||||
#: talerbank/app/templates/register.html:22
|
||||
#, python-brace-format
|
||||
msgid "Register to the {currency} bank!"
|
||||
msgstr "{currency}銀行に登録してください!"
|
||||
|
||||
#: talerbank/app/templates/register.html:30
|
||||
msgid "Back"
|
||||
msgstr "戻る"
|
||||
|
||||
#: talerbank/app/templates/register.html:39
|
||||
msgid ""
|
||||
"Sorry, this username is no longer available. Please choose another one!"
|
||||
msgstr "申し訳ありませんが、このユーザー名はご利用いただけなくなりました!"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:23
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr "引き出しを確認する"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:34
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{currency} Bank needs to verify that you intend to withdraw <b>{amount}</b> "
|
||||
"from <b>{exchange}</b>. To prove that you are the account owner, please "
|
||||
"answer the following "security question" (*):"
|
||||
msgstr ""
|
||||
"{currency}銀行は、 <b>{exchange}</b><b>から{amount}</b>を引き出すつもりであることを確認する必要があります。"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:38
|
||||
#, python-brace-format
|
||||
msgid "What is {question}?"
|
||||
msgstr "{question}とは何ですか?"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:64
|
||||
msgid ""
|
||||
"A real bank should ask for a PIN/TAN instead of a simple calculation. For "
|
||||
"example by sending a one time password to the customer's mobile or providing "
|
||||
"her a random password generator."
|
||||
msgstr ""
|
||||
"本物の銀行は、単純な計算ではなく、PIN/"
|
||||
"TANを要求するべきです。例えば、顧客の携帯電話にワンタイムパスワードを送信したり、ランダムパスワードジェネレータを提供したりします。"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:22
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr "ターラーウォレットに撤退する"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:66
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Looks like your browser doesn't support GNU Taler payments. You can try "
|
||||
"installing a <a href=\"{wallet_link}\">wallet browser extension</a>."
|
||||
msgstr ""
|
||||
"あなたのブラウザはGNU Talerの支払いをサポートしていないようです。<a href=\"{wallet_link}\""
|
||||
">ウォレットブラウザ拡張機能</a>をインストールしてみてください。"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:72
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr "このQRコードを使用して、モバイルウォレットに引き出すことができます。"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:77
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Click <a href=\"{taler_withdraw_uri}\">this link</a> to open your system's "
|
||||
"Taler wallet if it exists."
|
||||
msgstr ""
|
||||
"<a href=\"{taler_withdraw_uri}\">このリンク</a>をクリックして、システムにTalerウォレットがあれば開きます。"
|
||||
|
||||
#: talerbank/app/views.py:353
|
||||
msgid "Bad form submitted!"
|
||||
msgstr "不正なフォームが送信されました!"
|
||||
|
||||
#: talerbank/app/views.py:367
|
||||
msgid "Wire transfer successful!"
|
||||
msgstr "電信送金に成功しました!"
|
||||
|
||||
#: talerbank/app/views.py:520
|
||||
msgid "Registration successful!"
|
||||
msgstr "登録に成功しました!"
|
||||
|
||||
#: talerbank/app/views.py:1212
|
||||
msgid "Wrong CAPTCHA answer."
|
||||
msgstr "間違ったCAPTCHAの答え。"
|
||||
|
||||
#: talerbank/app/views.py:1223
|
||||
msgid "Withdrawal successful!"
|
||||
msgstr "撤退成功!"
|
|
@ -0,0 +1,292 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-20 13:09+0000\n"
|
||||
"PO-Revision-Date: 2021-03-20 15:15+0000\n"
|
||||
"Last-Translator: Choyi Whang <choyi.whang@gmail.com>\n"
|
||||
"Language-Team: Korean <http://weblate.taler.net/projects/gnu-taler/"
|
||||
"taler-bank/ko/>\n"
|
||||
"Language: ko\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 4.4.2\n"
|
||||
|
||||
#: talerbank/app/templates/404.html:23
|
||||
msgid "Error"
|
||||
msgstr "오류"
|
||||
|
||||
#: talerbank/app/templates/404.html:30
|
||||
msgid "Page not found!"
|
||||
msgstr "페이지를 찾을 수 없습니다!"
|
||||
|
||||
#: talerbank/app/templates/base.html:23
|
||||
#, python-brace-format
|
||||
msgid "{currency} Bank - Taler Demo"
|
||||
msgstr "{currency} 은행 - 탈러 데모"
|
||||
|
||||
#: talerbank/app/templates/base.html:74
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"This part of the demo shows how a bank that supports Taler directly would "
|
||||
"work. In addition to using your own bank account, you can also see the "
|
||||
"transaction history of some <a href=\"{public_accounts}\">Public Accounts</"
|
||||
"a>."
|
||||
msgstr ""
|
||||
"데모의 이 부분은 탈러를 직접 지원하는 은행이 어떻게 작동하는지 보여줍니다. 당신의 은행계좌를 사용하는 것에 더하여, 몇 개의 <a "
|
||||
"href=\"{public_accounts}\">공개 계정</a>의 거래 내역도 볼 수 있습니다."
|
||||
|
||||
#: talerbank/app/templates/base.html:80
|
||||
msgid "Introduction"
|
||||
msgstr "소개"
|
||||
|
||||
#: talerbank/app/templates/base.html:81
|
||||
msgid "Bank"
|
||||
msgstr "은행"
|
||||
|
||||
#: talerbank/app/templates/base.html:82
|
||||
msgid "Essay Shop"
|
||||
msgstr "에세이 샵"
|
||||
|
||||
#: talerbank/app/templates/base.html:83
|
||||
msgid "Donations"
|
||||
msgstr "기부"
|
||||
|
||||
#: talerbank/app/templates/base.html:84
|
||||
msgid "Tipping/Survey"
|
||||
msgstr "팁 / 설문조사"
|
||||
|
||||
#: talerbank/app/templates/base.html:94
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"You can learn more about Taler on our main <a href={taler_site}>website</a>."
|
||||
msgstr "Taler에 대한 자세한 내용은 메인 <a href={taler_site}>웹 사이트</a> 에서 확인할 수 있습니다."
|
||||
|
||||
#: talerbank/app/templates/login.html:22
|
||||
#, python-brace-format
|
||||
msgid "Welcome to the {currency} Bank!"
|
||||
msgstr "{currency} 은행에 오신 것을 환영합니다!"
|
||||
|
||||
#: talerbank/app/templates/login.html:29
|
||||
msgid "Please login!"
|
||||
msgstr "로그인 하세요!"
|
||||
|
||||
#: talerbank/app/templates/login.html:33
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr "사용자명과 비밀번호가 일치하지 않습니다. 다시 시도하세요."
|
||||
|
||||
#: talerbank/app/templates/login.html:40
|
||||
msgid ""
|
||||
"Your account doesn't have access to this page. To proceed, please login with "
|
||||
"an account that has access."
|
||||
msgstr "귀하의 계정은 이 페이지에 접근할 수 없습니다. 계속하기 위해, 접근 가능한 계정으로 로그인 해주세요."
|
||||
|
||||
#: talerbank/app/templates/login.html:43
|
||||
msgid "Please login to see this page."
|
||||
msgstr "이 페이지를 보려면 로그인하십시오."
|
||||
|
||||
#: talerbank/app/templates/login.html:59
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"If you are a new customer please <a href=\"{register_link}\">register</a>. "
|
||||
"Registration is fast and free, and it gives you a registration bonus of 100 "
|
||||
"{currency}"
|
||||
msgstr ""
|
||||
"신규 고객인 경우 <a href=\"{register_link}\">등록</a>하십시오. 등록은 빠르고 무료이며, 등록 보너스 100 "
|
||||
"{currency}를 받을 수 있습니다"
|
||||
|
||||
#: talerbank/app/templates/login.html:63
|
||||
msgid "Registrations are not open to the public."
|
||||
msgstr "등록은 일반인에게 공개되지 않습니다."
|
||||
|
||||
#: talerbank/app/templates/login.html:67
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"To view transactions of public accounts, please <a href="
|
||||
"\"{public_accounts}\">click here</a>."
|
||||
msgstr "공개 계정의 거래를 보려면 <a href=\"{public_accounts}\">여기</a> 를 클릭하십시오."
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:23
|
||||
#: talerbank/app/templates/profile_page.html:28
|
||||
msgid "Logout"
|
||||
msgstr "로그아웃"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:30
|
||||
msgid "Wire transfer"
|
||||
msgstr "송금"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:31
|
||||
msgid "Transfer money via the payto system:"
|
||||
msgstr "Payto 시스템을 통한 송금:"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:41
|
||||
msgid "payto address"
|
||||
msgstr "payto 주소"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:45
|
||||
msgid "Confirm"
|
||||
msgstr "확인"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:25
|
||||
#, python-brace-format
|
||||
msgid "Welcome <em>{name}</em>!"
|
||||
msgstr "<em>{name} 님,</em> 환영합니다!"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:33
|
||||
msgid "Bank account balance"
|
||||
msgstr "은행 계좌 잔액"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:51
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr "Taler 지갑으로 돈 인출"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:58
|
||||
msgid "Amount to withdraw"
|
||||
msgstr "인출할 금액"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:73
|
||||
msgid "Start withdrawal"
|
||||
msgstr "출금 시작"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:78
|
||||
msgid "Wire money"
|
||||
msgstr "송금"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:81
|
||||
msgid "Transactions for"
|
||||
msgstr "거래"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:87
|
||||
#: talerbank/app/templates/public_accounts.html:59
|
||||
msgid "Date"
|
||||
msgstr "날짜"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:88
|
||||
#: talerbank/app/templates/public_accounts.html:60
|
||||
msgid "Amount"
|
||||
msgstr "금액"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:89
|
||||
#: talerbank/app/templates/public_accounts.html:61
|
||||
msgid "Counterpart"
|
||||
msgstr "상대"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:90
|
||||
#: talerbank/app/templates/public_accounts.html:62
|
||||
msgid "Subject"
|
||||
msgstr "제목"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:107
|
||||
msgid "cancelled"
|
||||
msgstr "취소됨"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:116
|
||||
msgid "No transactions made to/from this account"
|
||||
msgstr "이 계정과의 거래 없음"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:21
|
||||
msgid "History of public accounts"
|
||||
msgstr "공개 계정 내역"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:71
|
||||
msgid "account"
|
||||
msgstr "계정"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:101
|
||||
#, python-brace-format
|
||||
msgid "No history for account #{account_number} ({account_name}) yet"
|
||||
msgstr "계좌 # {account_number} {account_name} 에 대한 관련 기록이 없습니다"
|
||||
|
||||
#: talerbank/app/templates/register.html:22
|
||||
#, python-brace-format
|
||||
msgid "Register to the {currency} bank!"
|
||||
msgstr "{currency} 은행에 등록하세요!"
|
||||
|
||||
#: talerbank/app/templates/register.html:30
|
||||
msgid "Back"
|
||||
msgstr "뒤로"
|
||||
|
||||
#: talerbank/app/templates/register.html:39
|
||||
msgid ""
|
||||
"Sorry, this username is no longer available. Please choose another one!"
|
||||
msgstr "죄송합니다, 해당 사용자 이름은 사용하실 수 없습니다. 다른 이름을 입력하세요!"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:23
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr "출금 확인"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:34
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{currency} Bank needs to verify that you intend to withdraw <b>{amount}</b> "
|
||||
"from <b>{exchange}</b>. To prove that you are the account owner, please "
|
||||
"answer the following "security question" (*):"
|
||||
msgstr ""
|
||||
"{currency} 은행은 본인의 의사로 <b>{exchange}</b>에서 <b>{amount}</b> 의 금액을 인출하려하는지 "
|
||||
"확인해야 합니다. 계좌 주인 당사자인지 확인을 위해 "보안 질문" 에 답해주시길 바랍니다. (*):"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:38
|
||||
#, python-brace-format
|
||||
msgid "What is {question}?"
|
||||
msgstr "{question}이 무엇입니까?"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:64
|
||||
msgid ""
|
||||
"A real bank should ask for a PIN/TAN instead of a simple calculation. For "
|
||||
"example by sending a one time password to the customer's mobile or providing "
|
||||
"her a random password generator."
|
||||
msgstr ""
|
||||
"실제 은행에서는 간단한 계산을 하는 대신 PIN/TAN 번호를 요구합니다. 예를 들어 고객의 핸드폰으로 일회성 비밀번호를 보내거나 랜덤 "
|
||||
"비밀번호를 발급받을 수 있게 신원 확인을 합니다."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:22
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr "Taler 지갑으로 출금"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:66
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Looks like your browser doesn't support GNU Taler payments. You can try "
|
||||
"installing a <a href=\"{wallet_link}\">wallet browser extension</a>."
|
||||
msgstr ""
|
||||
"브라우저가 GNU Taler 결제를 지원하지 않는 것 같습니다. <a href=\"{wallet_link}\">지갑 브라우저 확장자</"
|
||||
"a>로 시도해보세요."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:72
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr "이 QR 코드를 사용하여 모바일 지갑으로 인출할 수 있습니다:"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:77
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Click <a href=\"{taler_withdraw_uri}\">this link</a> to open your system's "
|
||||
"Taler wallet if it exists."
|
||||
msgstr ""
|
||||
"<a href=\"{taler_withdraw_uri}\">이 링크</a> 를 클릭하면 시스템의 Taler 지갑이 존재할 시 열립니다."
|
||||
|
||||
#: talerbank/app/views.py:353
|
||||
msgid "Bad form submitted!"
|
||||
msgstr "잘못된 양식이 제출되었습니다!"
|
||||
|
||||
#: talerbank/app/views.py:367
|
||||
msgid "Wire transfer successful!"
|
||||
msgstr "성공적으로 이체!"
|
||||
|
||||
#: talerbank/app/views.py:520
|
||||
msgid "Registration successful!"
|
||||
msgstr "성공적으로 등록!"
|
||||
|
||||
#: talerbank/app/views.py:1212
|
||||
msgid "Wrong CAPTCHA answer."
|
||||
msgstr "CAPTCHA 답변이 틀렸습니다."
|
||||
|
||||
#: talerbank/app/views.py:1223
|
||||
msgid "Withdrawal successful!"
|
||||
msgstr "인출 성공!"
|
|
@ -0,0 +1,313 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-20 13:09+0000\n"
|
||||
"PO-Revision-Date: 2021-02-27 20:12+0000\n"
|
||||
"Last-Translator: Salomé Mariano <salomemariano@gmail.com>\n"
|
||||
"Language-Team: Portuguese <http://weblate.taler.net/projects/gnu-taler/"
|
||||
"taler-bank/pt/>\n"
|
||||
"Language: pt\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.4.2\n"
|
||||
|
||||
#: talerbank/app/templates/404.html:23
|
||||
msgid "Error"
|
||||
msgstr "Erro"
|
||||
|
||||
#: talerbank/app/templates/404.html:30
|
||||
msgid "Page not found!"
|
||||
msgstr "Página não encontrada!"
|
||||
|
||||
#: talerbank/app/templates/base.html:23
|
||||
#, python-brace-format
|
||||
msgid "{currency} Bank - Taler Demo"
|
||||
msgstr "{currency} Banco - Demonstração da Taler"
|
||||
|
||||
#: talerbank/app/templates/base.html:74
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"This part of the demo shows how a bank that supports Taler directly would "
|
||||
"work. In addition to using your own bank account, you can also see the "
|
||||
"transaction history of some <a href=\"{public_accounts}\">Public Accounts</"
|
||||
"a>."
|
||||
msgstr ""
|
||||
"Esta parte da demonstração mostra como funcionaria um banco que suporta "
|
||||
"diretamente o Taler. Além de usar a sua própria conta bancária, você também "
|
||||
"pode ver o histórico de transações de algumas <a href=\"{public_accounts}\""
|
||||
">Contas Públicas</a>."
|
||||
|
||||
#: talerbank/app/templates/base.html:80
|
||||
msgid "Introduction"
|
||||
msgstr "Introdução"
|
||||
|
||||
#: talerbank/app/templates/base.html:81
|
||||
msgid "Bank"
|
||||
msgstr "Banco"
|
||||
|
||||
#: talerbank/app/templates/base.html:82
|
||||
msgid "Essay Shop"
|
||||
msgstr "Loja de Ensaios"
|
||||
|
||||
#: talerbank/app/templates/base.html:83
|
||||
msgid "Donations"
|
||||
msgstr "Doações"
|
||||
|
||||
#: talerbank/app/templates/base.html:84
|
||||
msgid "Tipping/Survey"
|
||||
msgstr "Gorjeta/Inquérito"
|
||||
|
||||
#: talerbank/app/templates/base.html:94
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"You can learn more about Taler on our main <a href={taler_site}>website</a>."
|
||||
msgstr ""
|
||||
"Podes aprender mais sobre a Taler no nosso <a href={taler_site}>site</a> "
|
||||
"principal."
|
||||
|
||||
#: talerbank/app/templates/login.html:22
|
||||
#, python-brace-format
|
||||
msgid "Welcome to the {currency} Bank!"
|
||||
msgstr "Boas vindas ao Banco {currency}!"
|
||||
|
||||
#: talerbank/app/templates/login.html:29
|
||||
msgid "Please login!"
|
||||
msgstr "Por favor inicie sessão!"
|
||||
|
||||
#: talerbank/app/templates/login.html:33
|
||||
#, fuzzy
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr ""
|
||||
"O seu nome de usuário e senha não corresponderm. Por favor tente novamente."
|
||||
|
||||
#: talerbank/app/templates/login.html:40
|
||||
msgid ""
|
||||
"Your account doesn't have access to this page. To proceed, please login with "
|
||||
"an account that has access."
|
||||
msgstr ""
|
||||
"A sua conta não tem acesso a esta página. Para avançar, por favor inicie "
|
||||
"sessão com uma conta que tenha acesso."
|
||||
|
||||
#: talerbank/app/templates/login.html:43
|
||||
msgid "Please login to see this page."
|
||||
msgstr "Por favor inicie sessão para ver esta página."
|
||||
|
||||
#: talerbank/app/templates/login.html:59
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"If you are a new customer please <a href=\"{register_link}\">register</a>. "
|
||||
"Registration is fast and free, and it gives you a registration bonus of 100 "
|
||||
"{currency}"
|
||||
msgstr ""
|
||||
"Se for um cliente novo, por favor <a href=\"{register_link}\">crie uma "
|
||||
"conta</a>. É rápido e gratuito e você recebe um bónus de 100 {currency}"
|
||||
|
||||
#: talerbank/app/templates/login.html:63
|
||||
#, fuzzy
|
||||
msgid "Registrations are not open to the public."
|
||||
msgstr "A criação de contas não está aberta ao público."
|
||||
|
||||
#: talerbank/app/templates/login.html:67
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"To view transactions of public accounts, please <a href="
|
||||
"\"{public_accounts}\">click here</a>."
|
||||
msgstr ""
|
||||
"Para ver as transações de contas públicas, por favor <a href=\""
|
||||
"{public_accounts}\">clique aqui</a>."
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:23
|
||||
#: talerbank/app/templates/profile_page.html:28
|
||||
msgid "Logout"
|
||||
msgstr "Terminar sessão"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:30
|
||||
msgid "Wire transfer"
|
||||
msgstr "Transferência bancária"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:31
|
||||
msgid "Transfer money via the payto system:"
|
||||
msgstr "Transferir dinheiro através do sistema payto:"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:41
|
||||
msgid "payto address"
|
||||
msgstr "endereço payto"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:45
|
||||
msgid "Confirm"
|
||||
msgstr "Confirmar"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:25
|
||||
#, python-brace-format
|
||||
msgid "Welcome <em>{name}</em>!"
|
||||
msgstr "Boas vindas <em>{name}</em>!"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:33
|
||||
msgid "Bank account balance"
|
||||
msgstr "Saldo da conta bancária"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:51
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr "Sacar Dinheiro para uma carteira Taler"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:58
|
||||
msgid "Amount to withdraw"
|
||||
msgstr "Quantia a sacar"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:73
|
||||
#, fuzzy
|
||||
msgid "Start withdrawal"
|
||||
msgstr "Iniciar saque"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:78
|
||||
msgid "Wire money"
|
||||
msgstr "Transferir dinheiro"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:81
|
||||
msgid "Transactions for"
|
||||
msgstr "Transações para"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:87
|
||||
#: talerbank/app/templates/public_accounts.html:59
|
||||
msgid "Date"
|
||||
msgstr "Data"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:88
|
||||
#: talerbank/app/templates/public_accounts.html:60
|
||||
msgid "Amount"
|
||||
msgstr "Quantia"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:89
|
||||
#: talerbank/app/templates/public_accounts.html:61
|
||||
#, fuzzy
|
||||
msgid "Counterpart"
|
||||
msgstr "Homólogo"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:90
|
||||
#: talerbank/app/templates/public_accounts.html:62
|
||||
msgid "Subject"
|
||||
msgstr "Assunto"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:107
|
||||
msgid "cancelled"
|
||||
msgstr "cancelada"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:116
|
||||
msgid "No transactions made to/from this account"
|
||||
msgstr "Não foram feitas transações a partir/para esta conta"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:21
|
||||
msgid "History of public accounts"
|
||||
msgstr "Histórico de contas públicas"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:71
|
||||
msgid "account"
|
||||
msgstr "conta"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:101
|
||||
#, python-brace-format
|
||||
msgid "No history for account #{account_number} ({account_name}) yet"
|
||||
msgstr "A conta #{account_number} ({account_name}) ainda não tem um histórico"
|
||||
|
||||
#: talerbank/app/templates/register.html:22
|
||||
#, fuzzy, python-brace-format
|
||||
msgid "Register to the {currency} bank!"
|
||||
msgstr "Criar uma conta com o banco {currency}!"
|
||||
|
||||
#: talerbank/app/templates/register.html:30
|
||||
msgid "Back"
|
||||
msgstr "Voltar"
|
||||
|
||||
#: talerbank/app/templates/register.html:39
|
||||
msgid ""
|
||||
"Sorry, this username is no longer available. Please choose another one!"
|
||||
msgstr ""
|
||||
"Pedimos desculpa, mas este nome de usuário já não está disponível. Por favor "
|
||||
"escolha outro!"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:23
|
||||
#, fuzzy
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr "Confirmar Saque"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:34
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{currency} Bank needs to verify that you intend to withdraw <b>{amount}</b> "
|
||||
"from <b>{exchange}</b>. To prove that you are the account owner, please "
|
||||
"answer the following "security question" (*):"
|
||||
msgstr ""
|
||||
"O Banco {currency} precisa de confirmar que pretendes sacar <b>{amount}</b> "
|
||||
"de <b>{exchange}</b>. Para provar que esta conta é sua, por favor responda a "
|
||||
"esta "perqunta de segurança" (*):"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:38
|
||||
#, fuzzy, python-brace-format
|
||||
msgid "What is {question}?"
|
||||
msgstr "O que é {question}?"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:64
|
||||
msgid ""
|
||||
"A real bank should ask for a PIN/TAN instead of a simple calculation. For "
|
||||
"example by sending a one time password to the customer's mobile or providing "
|
||||
"her a random password generator."
|
||||
msgstr ""
|
||||
"Um banco real deve pedir um PIN/TAN em vez de um cálculo simples, por "
|
||||
"exemplo enviando uma palavra passe de uso único para o celular da cliente ou "
|
||||
"disponibilizando um gerador de senhas aleatórias."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:22
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr "Sacar para uma Carteira Taler"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:66
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"Looks like your browser doesn't support GNU Taler payments. You can try "
|
||||
"installing a <a href=\"{wallet_link}\">wallet browser extension</a>."
|
||||
msgstr ""
|
||||
"Parece que o seu navegador não suporta pagamentos usando a GNU Taler. Pode "
|
||||
"tentar instalar uma <a href=\"{wallet_link}\">extensão para navegador</a>."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:72
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr "Pode usar este código QR para sacar dinheiro para a sua carteira móvel:"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:77
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Click <a href=\"{taler_withdraw_uri}\">this link</a> to open your system's "
|
||||
"Taler wallet if it exists."
|
||||
msgstr ""
|
||||
"Clique <a href=\"{taler_withdraw_uri}\">neste link</a> para abrir a carteira "
|
||||
"Taler do seu sistema, se a tiver."
|
||||
|
||||
#: talerbank/app/views.py:353
|
||||
#, fuzzy
|
||||
msgid "Bad form submitted!"
|
||||
msgstr "Formulário incorreto submetido!"
|
||||
|
||||
#: talerbank/app/views.py:367
|
||||
msgid "Wire transfer successful!"
|
||||
msgstr "Transferência bancária bem sucedida!"
|
||||
|
||||
#: talerbank/app/views.py:520
|
||||
msgid "Registration successful!"
|
||||
msgstr "Conta criada com sucesso!"
|
||||
|
||||
#: talerbank/app/views.py:1212
|
||||
msgid "Wrong CAPTCHA answer."
|
||||
msgstr "Resposta CAPTCHA incorreta."
|
||||
|
||||
#: talerbank/app/views.py:1223
|
||||
#, fuzzy
|
||||
msgid "Withdrawal successful!"
|
||||
msgstr "Saque bem sucedido!"
|
|
@ -0,0 +1,310 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-20 13:09+0000\n"
|
||||
"PO-Revision-Date: 2021-05-20 00:51+0000\n"
|
||||
"Last-Translator: Yulia Greben <yulia.greben@gmail.com>\n"
|
||||
"Language-Team: Russian <http://weblate.taler.net/projects/gnu-taler/"
|
||||
"taler-bank/ru/>\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 4.4.2\n"
|
||||
|
||||
#: talerbank/app/templates/404.html:23
|
||||
msgid "Error"
|
||||
msgstr "Ошибка"
|
||||
|
||||
#: talerbank/app/templates/404.html:30
|
||||
msgid "Page not found!"
|
||||
msgstr "Страница не найдена!"
|
||||
|
||||
#: talerbank/app/templates/base.html:23
|
||||
#, python-brace-format
|
||||
msgid "{currency} Bank - Taler Demo"
|
||||
msgstr "{currency} Банк - демоверсия Taler"
|
||||
|
||||
#: talerbank/app/templates/base.html:74
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"This part of the demo shows how a bank that supports Taler directly would "
|
||||
"work. In addition to using your own bank account, you can also see the "
|
||||
"transaction history of some <a href=\"{public_accounts}\">Public Accounts</"
|
||||
"a>."
|
||||
msgstr ""
|
||||
"В этой части демоверсии продемонстрирована работа банка, напрямую "
|
||||
"поддерживающего Taler. Вы можете не только использовать ваш банковский счёт, "
|
||||
"а также видеть историю денежных операций по некоторым <a href=\""
|
||||
"{public_accounts}\">доступным для публичного просмотра счетам</a>."
|
||||
|
||||
#: talerbank/app/templates/base.html:80
|
||||
msgid "Introduction"
|
||||
msgstr "Введение"
|
||||
|
||||
#: talerbank/app/templates/base.html:81
|
||||
msgid "Bank"
|
||||
msgstr "Банк"
|
||||
|
||||
#: talerbank/app/templates/base.html:82
|
||||
msgid "Essay Shop"
|
||||
msgstr "Демо-магазин"
|
||||
|
||||
#: talerbank/app/templates/base.html:83
|
||||
msgid "Donations"
|
||||
msgstr "Поддержать проект"
|
||||
|
||||
#: talerbank/app/templates/base.html:84
|
||||
msgid "Tipping/Survey"
|
||||
msgstr "Опрос"
|
||||
|
||||
#: talerbank/app/templates/base.html:94
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"You can learn more about Taler on our main <a href={taler_site}>website</a>."
|
||||
msgstr ""
|
||||
"Подробнее о Taler можно прочитать на нашем <a href={taler_site}>сайте</a>."
|
||||
|
||||
#: talerbank/app/templates/login.html:22
|
||||
#, python-brace-format
|
||||
msgid "Welcome to the {currency} Bank!"
|
||||
msgstr "Добро пожаловать в {currency} Банк!"
|
||||
|
||||
#: talerbank/app/templates/login.html:29
|
||||
msgid "Please login!"
|
||||
msgstr "Пожалуйста, войдите в систему!"
|
||||
|
||||
#: talerbank/app/templates/login.html:33
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr ""
|
||||
"Ваши имя пользователя и пароль не совпадают. Пожалуйста, попробуйте ввести "
|
||||
"имя пользователя и пароль ещё раз."
|
||||
|
||||
#: talerbank/app/templates/login.html:40
|
||||
msgid ""
|
||||
"Your account doesn't have access to this page. To proceed, please login with "
|
||||
"an account that has access."
|
||||
msgstr ""
|
||||
"У вашей учётной записи нет доступа к данной странице. Чтобы продолжить, "
|
||||
"войдите в систему с помощью учётной записи, имеющей доступ к данной странице."
|
||||
|
||||
#: talerbank/app/templates/login.html:43
|
||||
msgid "Please login to see this page."
|
||||
msgstr "Для просмотра данной страницы, пожалуйста, войдите в систему."
|
||||
|
||||
#: talerbank/app/templates/login.html:59
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"If you are a new customer please <a href=\"{register_link}\">register</a>. "
|
||||
"Registration is fast and free, and it gives you a registration bonus of 100 "
|
||||
"{currency}"
|
||||
msgstr ""
|
||||
"Если вы новый пользователь, пожалуйста, зарегистрируйтесь <a href=\""
|
||||
"{register_link}\">здесь</a>. Регистрация бесплатная и не займёт много "
|
||||
"времени. Вы также получите бонус в размере 100 {currency}"
|
||||
|
||||
#: talerbank/app/templates/login.html:63
|
||||
msgid "Registrations are not open to the public."
|
||||
msgstr "Закрытая для публики регистрация."
|
||||
|
||||
#: talerbank/app/templates/login.html:67
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"To view transactions of public accounts, please <a href="
|
||||
"\"{public_accounts}\">click here</a>."
|
||||
msgstr ""
|
||||
"Информацию о денежных операциях по счетам, доступным для публичного "
|
||||
"просмотра, можно увидеть <a href=\"{public_accounts}\">здесь</a>."
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:23
|
||||
#: talerbank/app/templates/profile_page.html:28
|
||||
msgid "Logout"
|
||||
msgstr "Выйти"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:30
|
||||
msgid "Wire transfer"
|
||||
msgstr "Перевод"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:31
|
||||
msgid "Transfer money via the payto system:"
|
||||
msgstr "Перевести деньги через Payto:"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:41
|
||||
msgid "payto address"
|
||||
msgstr "адрес Payto"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:45
|
||||
msgid "Confirm"
|
||||
msgstr "Подтвердить"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:25
|
||||
#, python-brace-format
|
||||
msgid "Welcome <em>{name}</em>!"
|
||||
msgstr "Добро пожаловать <em>{name}</em>!"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:33
|
||||
msgid "Bank account balance"
|
||||
msgstr "Баланс банковского счёта"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:51
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr "Вывести деньги в кошелёк Taler"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:58
|
||||
msgid "Amount to withdraw"
|
||||
msgstr "Сумма для вывода средств"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:73
|
||||
msgid "Start withdrawal"
|
||||
msgstr "Начать вывод средств"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:78
|
||||
msgid "Wire money"
|
||||
msgstr "Перевести деньги"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:81
|
||||
msgid "Transactions for"
|
||||
msgstr "Транзакции для"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:87
|
||||
#: talerbank/app/templates/public_accounts.html:59
|
||||
msgid "Date"
|
||||
msgstr "Дата"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:88
|
||||
#: talerbank/app/templates/public_accounts.html:60
|
||||
msgid "Amount"
|
||||
msgstr "Сумма"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:89
|
||||
#: talerbank/app/templates/public_accounts.html:61
|
||||
msgid "Counterpart"
|
||||
msgstr "Получатель"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:90
|
||||
#: talerbank/app/templates/public_accounts.html:62
|
||||
msgid "Subject"
|
||||
msgstr "Описание"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:107
|
||||
msgid "cancelled"
|
||||
msgstr "отменена"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:116
|
||||
msgid "No transactions made to/from this account"
|
||||
msgstr "Нет транзакций"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:21
|
||||
msgid "History of public accounts"
|
||||
msgstr "История счетов, доступных для публичного просмотра"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:71
|
||||
msgid "account"
|
||||
msgstr "счёт"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:101
|
||||
#, python-brace-format
|
||||
msgid "No history for account #{account_number} ({account_name}) yet"
|
||||
msgstr "Нет данных об истории счёта #{account_number} ({account_name})"
|
||||
|
||||
#: talerbank/app/templates/register.html:22
|
||||
#, python-brace-format
|
||||
msgid "Register to the {currency} bank!"
|
||||
msgstr "Зарегистрируйтесь в {currency} Банке!"
|
||||
|
||||
#: talerbank/app/templates/register.html:30
|
||||
msgid "Back"
|
||||
msgstr "Назад"
|
||||
|
||||
#: talerbank/app/templates/register.html:39
|
||||
msgid ""
|
||||
"Sorry, this username is no longer available. Please choose another one!"
|
||||
msgstr ""
|
||||
"Извините, это имя пользователя уже занято. Пожалуйста, выберите другое!"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:23
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr "Подтвердить вывод средств"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:34
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{currency} Bank needs to verify that you intend to withdraw <b>{amount}</b> "
|
||||
"from <b>{exchange}</b>. To prove that you are the account owner, please "
|
||||
"answer the following "security question" (*):"
|
||||
msgstr ""
|
||||
"{currency} Банк должен проверить, что именно вы хотите вывести <b>{amount}</"
|
||||
"b> с <b>{exchange}</b>. Пожалуйста, ответьте на "приведённый ниже "
|
||||
"вопрос" для подтверждения того, что именно вы являетесь владельцем "
|
||||
"данной учётной записи (*):"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:38
|
||||
#, python-brace-format
|
||||
msgid "What is {question}?"
|
||||
msgstr "Сколько будет {question}?"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:64
|
||||
msgid ""
|
||||
"A real bank should ask for a PIN/TAN instead of a simple calculation. For "
|
||||
"example by sending a one time password to the customer's mobile or providing "
|
||||
"her a random password generator."
|
||||
msgstr ""
|
||||
"В реальной, а не тестовой ситуации, банк должен запросить у клиента PIN/TAN-"
|
||||
"коды вместо решения элементарного вычислительного примера. Например, клиент "
|
||||
"получит на свой мобильный телефон одноразовый пароль или генератор случайных "
|
||||
"паролей."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:22
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr "Вывести средства в Taler Кошелёк"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:66
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Looks like your browser doesn't support GNU Taler payments. You can try "
|
||||
"installing a <a href=\"{wallet_link}\">wallet browser extension</a>."
|
||||
msgstr ""
|
||||
"Ваш браузер не поддерживает платежи GNU Taler. Попробуйте установить <a href="
|
||||
"\"{wallet_link}\">расширение браузера для кошелька</a>."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:72
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr ""
|
||||
"Вы может использовать QR-код для вывода средств на ваш мобильный кошелёк:"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:77
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Click <a href=\"{taler_withdraw_uri}\">this link</a> to open your system's "
|
||||
"Taler wallet if it exists."
|
||||
msgstr ""
|
||||
"Если у вас установлен кошелёк Taler, вы можете открыть его, щёлкнув «мышью» "
|
||||
"на <a href=\"{taler_withdraw_uri}\">ссылке</a>."
|
||||
|
||||
#: talerbank/app/views.py:353
|
||||
msgid "Bad form submitted!"
|
||||
msgstr "Ошибки при заполнении формы!"
|
||||
|
||||
#: talerbank/app/views.py:367
|
||||
msgid "Wire transfer successful!"
|
||||
msgstr "Перевод успешно завершён!"
|
||||
|
||||
#: talerbank/app/views.py:520
|
||||
msgid "Registration successful!"
|
||||
msgstr "Регистрация прошла успешно!"
|
||||
|
||||
#: talerbank/app/views.py:1212
|
||||
msgid "Wrong CAPTCHA answer."
|
||||
msgstr "Неправильно введена CAPTCHA."
|
||||
|
||||
#: talerbank/app/views.py:1223
|
||||
msgid "Withdrawal successful!"
|
||||
msgstr "Вывод средств успешно завершён!"
|
|
@ -0,0 +1,305 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-20 13:09+0000\n"
|
||||
"PO-Revision-Date: 2021-02-02 19:26+0000\n"
|
||||
"Last-Translator: Stefan Lidstrom <stefan.lidstrom@tanker.se>\n"
|
||||
"Language-Team: Swedish <http://weblate.taler.net/projects/gnu-taler/"
|
||||
"taler-bank/sv/>\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.4.2\n"
|
||||
|
||||
#: talerbank/app/templates/404.html:23
|
||||
msgid "Error"
|
||||
msgstr "Fel"
|
||||
|
||||
#: talerbank/app/templates/404.html:30
|
||||
msgid "Page not found!"
|
||||
msgstr "Sidan hittades inte!"
|
||||
|
||||
#: talerbank/app/templates/base.html:23
|
||||
#, python-brace-format
|
||||
msgid "{currency} Bank - Taler Demo"
|
||||
msgstr "{currency} Bank - Taler Demo"
|
||||
|
||||
#: talerbank/app/templates/base.html:74
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"This part of the demo shows how a bank that supports Taler directly would "
|
||||
"work. In addition to using your own bank account, you can also see the "
|
||||
"transaction history of some <a href=\"{public_accounts}\">Public Accounts</"
|
||||
"a>."
|
||||
msgstr ""
|
||||
"Denna del av demon visar hur en bank som stöder Taler direkt skulle fungera. "
|
||||
"Förutom att använda ditt eget bankkonto kan du också se "
|
||||
"transaktionshistoriken för vissa <a href=\"{public_accounts}\"> offentliga "
|
||||
"konton </a>."
|
||||
|
||||
#: talerbank/app/templates/base.html:80
|
||||
msgid "Introduction"
|
||||
msgstr "Inledning"
|
||||
|
||||
#: talerbank/app/templates/base.html:81
|
||||
msgid "Bank"
|
||||
msgstr "Bank"
|
||||
|
||||
#: talerbank/app/templates/base.html:82
|
||||
msgid "Essay Shop"
|
||||
msgstr "Artiklar att köpa"
|
||||
|
||||
#: talerbank/app/templates/base.html:83
|
||||
msgid "Donations"
|
||||
msgstr "Donationer"
|
||||
|
||||
#: talerbank/app/templates/base.html:84
|
||||
msgid "Tipping/Survey"
|
||||
msgstr "Enkät/Belöning"
|
||||
|
||||
#: talerbank/app/templates/base.html:94
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"You can learn more about Taler on our main <a href={taler_site}>website</a>."
|
||||
msgstr ""
|
||||
"Du kan lära dig mer om GNU Taler på vår <a href=\"{taler_site}\">webb</a> ."
|
||||
|
||||
#: talerbank/app/templates/login.html:22
|
||||
#, python-brace-format
|
||||
msgid "Welcome to the {currency} Bank!"
|
||||
msgstr "Välkommen till {currency} Banken!"
|
||||
|
||||
#: talerbank/app/templates/login.html:29
|
||||
msgid "Please login!"
|
||||
msgstr "Vänligen logga in!"
|
||||
|
||||
#: talerbank/app/templates/login.html:33
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr "Ditt användarnamn och lösenord matchade inte. Vänligen försök igen."
|
||||
|
||||
#: talerbank/app/templates/login.html:40
|
||||
msgid ""
|
||||
"Your account doesn't have access to this page. To proceed, please login with "
|
||||
"an account that has access."
|
||||
msgstr ""
|
||||
"Ditt konto har inte åtkomst till den här sidan. Logga in med ett konto som "
|
||||
"har åtkomst för att fortsätta."
|
||||
|
||||
#: talerbank/app/templates/login.html:43
|
||||
msgid "Please login to see this page."
|
||||
msgstr "Vänligen logga in för att se denna sida."
|
||||
|
||||
#: talerbank/app/templates/login.html:59
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"If you are a new customer please <a href=\"{register_link}\">register</a>. "
|
||||
"Registration is fast and free, and it gives you a registration bonus of 100 "
|
||||
"{currency}"
|
||||
msgstr ""
|
||||
"Om du är ny kund vänligen <a href=\"{register_link}\"> registrera dig </a>. "
|
||||
"Registreringen är snabb och gratis, och det ger dig en registreringsbonus på "
|
||||
"100 {currency}"
|
||||
|
||||
#: talerbank/app/templates/login.html:63
|
||||
msgid "Registrations are not open to the public."
|
||||
msgstr "Registreringar är inte öppna för allmänheten."
|
||||
|
||||
#: talerbank/app/templates/login.html:67
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"To view transactions of public accounts, please <a href="
|
||||
"\"{public_accounts}\">click here</a>."
|
||||
msgstr ""
|
||||
"<a href=\"{public_accounts}\">Klicka här för</a> att se transaktioner med "
|
||||
"offentliga konton."
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:23
|
||||
#: talerbank/app/templates/profile_page.html:28
|
||||
msgid "Logout"
|
||||
msgstr "Logga ut"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:30
|
||||
msgid "Wire transfer"
|
||||
msgstr "Banköverföring"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:31
|
||||
msgid "Transfer money via the payto system:"
|
||||
msgstr "Överför pengar via betalningssystemet:"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:41
|
||||
msgid "payto address"
|
||||
msgstr "betalningsadress"
|
||||
|
||||
#: talerbank/app/templates/payto_wiretransfer.html:45
|
||||
msgid "Confirm"
|
||||
msgstr "Bekräfta"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:25
|
||||
#, python-brace-format
|
||||
msgid "Welcome <em>{name}</em>!"
|
||||
msgstr "Välkommen <em>{name}</em> !"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:33
|
||||
msgid "Bank account balance"
|
||||
msgstr "Saldo på bankkontot"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:51
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr "För över pengar till en Taler-plånbok"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:58
|
||||
msgid "Amount to withdraw"
|
||||
msgstr "Summa att överföra"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:73
|
||||
msgid "Start withdrawal"
|
||||
msgstr "Starta uttag"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:78
|
||||
msgid "Wire money"
|
||||
msgstr "Överföra pengar"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:81
|
||||
msgid "Transactions for"
|
||||
msgstr "Transaktioner för"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:87
|
||||
#: talerbank/app/templates/public_accounts.html:59
|
||||
msgid "Date"
|
||||
msgstr "Datum"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:88
|
||||
#: talerbank/app/templates/public_accounts.html:60
|
||||
msgid "Amount"
|
||||
msgstr "Belopp"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:89
|
||||
#: talerbank/app/templates/public_accounts.html:61
|
||||
msgid "Counterpart"
|
||||
msgstr "Motpart"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:90
|
||||
#: talerbank/app/templates/public_accounts.html:62
|
||||
msgid "Subject"
|
||||
msgstr "Ämne"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:107
|
||||
msgid "cancelled"
|
||||
msgstr "avbruten"
|
||||
|
||||
#: talerbank/app/templates/profile_page.html:116
|
||||
msgid "No transactions made to/from this account"
|
||||
msgstr "Inga transaktioner gjorda till/från detta konto"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:21
|
||||
msgid "History of public accounts"
|
||||
msgstr "Historik över offentliga konton"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:71
|
||||
msgid "account"
|
||||
msgstr "konto"
|
||||
|
||||
#: talerbank/app/templates/public_accounts.html:101
|
||||
#, python-brace-format
|
||||
msgid "No history for account #{account_number} ({account_name}) yet"
|
||||
msgstr "Ingen historik för konto #{account_number} ({account_name}) ännu"
|
||||
|
||||
#: talerbank/app/templates/register.html:22
|
||||
#, python-brace-format
|
||||
msgid "Register to the {currency} bank!"
|
||||
msgstr "Registrera dig i {currency} banken!"
|
||||
|
||||
#: talerbank/app/templates/register.html:30
|
||||
msgid "Back"
|
||||
msgstr "Tillbaka"
|
||||
|
||||
#: talerbank/app/templates/register.html:39
|
||||
msgid ""
|
||||
"Sorry, this username is no longer available. Please choose another one!"
|
||||
msgstr ""
|
||||
"Tyvärr, det här användarnamnet är inte längre tillgänglig. Vänligen väl ett "
|
||||
"annat!"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:23
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr "Bekräfta uttag"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:34
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{currency} Bank needs to verify that you intend to withdraw <b>{amount}</b> "
|
||||
"from <b>{exchange}</b>. To prove that you are the account owner, please "
|
||||
"answer the following "security question" (*):"
|
||||
msgstr ""
|
||||
"{currency} Banken måste verifiera att du tänker ta ut <b> {amount} </b> från "
|
||||
"<b> {exchange} </b>. För att bevisa att du är kontoägare, svara på följande "
|
||||
""säkerhetsfråga" (*):"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:38
|
||||
#, python-brace-format
|
||||
msgid "What is {question}?"
|
||||
msgstr "Vad är {question}?"
|
||||
|
||||
#: talerbank/app/templates/withdraw_confirm.html:64
|
||||
msgid ""
|
||||
"A real bank should ask for a PIN/TAN instead of a simple calculation. For "
|
||||
"example by sending a one time password to the customer's mobile or providing "
|
||||
"her a random password generator."
|
||||
msgstr ""
|
||||
"En riktig bank bör be om ett lösenord/kod istället för en enkel beräkning. "
|
||||
"Till exempel genom att skicka ett engångslösenord till kundens mobil eller "
|
||||
"ge hen ett slumpmässigt lösenord."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:22
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr "Gör uttag till en Taler plånbok"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:66
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Looks like your browser doesn't support GNU Taler payments. You can try "
|
||||
"installing a <a href=\"{wallet_link}\">wallet browser extension</a>."
|
||||
msgstr ""
|
||||
"Det verkar som om din webbläsare inte stöder GNU Taler-betalningar. Du kan "
|
||||
"försöka installera ett <a href=\"{wallet_link}\">tillägg</a>."
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:72
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr "Du kan använda den här QR-koden för att överföra till din mobilplånbok:"
|
||||
|
||||
#: talerbank/app/templates/withdraw_show.html:77
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Click <a href=\"{taler_withdraw_uri}\">this link</a> to open your system's "
|
||||
"Taler wallet if it exists."
|
||||
msgstr ""
|
||||
"Klicka på den <a href=\"{taler_withdraw_uri}\">här länken för</a> att öppna "
|
||||
"systemets Taler-plånbok om den finns."
|
||||
|
||||
#: talerbank/app/views.py:353
|
||||
msgid "Bad form submitted!"
|
||||
msgstr "Felaktigt formulär inskickat!"
|
||||
|
||||
#: talerbank/app/views.py:367
|
||||
msgid "Wire transfer successful!"
|
||||
msgstr "Banköverföring lyckades!"
|
||||
|
||||
#: talerbank/app/views.py:520
|
||||
msgid "Registration successful!"
|
||||
msgstr "Registreringen lyckades!"
|
||||
|
||||
#: talerbank/app/views.py:1212
|
||||
msgid "Wrong CAPTCHA answer."
|
||||
msgstr "Fel CAPTCHA-svar."
|
||||
|
||||
#: talerbank/app/views.py:1223
|
||||
msgid "Withdrawal successful!"
|
||||
msgstr "Uttag lyckades!"
|
|
@ -0,0 +1,70 @@
|
|||
##
|
||||
# This file is part of TALER
|
||||
# (C) 2014, 2015, 2106 Taler Systems SA
|
||||
#
|
||||
# TALER 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,
|
||||
# or (at your option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not,
|
||||
# see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# @author Marcello Stanisci
|
||||
# @author Florian Dold
|
||||
# @brief Create the basic accounts to make the demo bank work.
|
||||
|
||||
import sys
|
||||
import logging
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.utils import ProgrammingError, OperationalError
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
from ...models import BankAccount
|
||||
from ...views import wire_transfer
|
||||
from taler.util.amount import Amount
|
||||
import getpass
|
||||
import uuid
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
LOGGER.setLevel(logging.INFO)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Add bank accounts."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"accountname", type=str, help="Login name of the new bank account"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--public", action="store_true", help="Make the bank account public"
|
||||
)
|
||||
|
||||
##
|
||||
# Django-specific definition to invoke the account creator
|
||||
# @a make_account; it iterates over the list of basic accounts
|
||||
# (defined in the settings) and invoke the account creator
|
||||
# for each one of them.
|
||||
def handle(self, *args, **options):
|
||||
accountname = options["accountname"]
|
||||
try:
|
||||
existing_user = User.objects.get(username=accountname)
|
||||
except User.DoesNotExist:
|
||||
BankAccount(
|
||||
user=User.objects.create_user(
|
||||
username=accountname, password=str(uuid.uuid4())
|
||||
),
|
||||
is_public=False,
|
||||
).save()
|
||||
print(
|
||||
f"Created new bank account {accountname} (password set to random password)"
|
||||
)
|
||||
else:
|
||||
print(f"Bank account {accountname} already exists.")
|
|
@ -0,0 +1,66 @@
|
|||
##
|
||||
# This file is part of TALER
|
||||
# (C) 2014, 2015, 2106 Taler Systems SA
|
||||
#
|
||||
# TALER 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,
|
||||
# or (at your option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not,
|
||||
# see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# @author Marcello Stanisci
|
||||
# @author Florian Dold
|
||||
# @brief Create the basic accounts to make the demo bank work.
|
||||
|
||||
import sys
|
||||
import logging
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.utils import ProgrammingError, OperationalError
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
from ...models import BankAccount
|
||||
from ...views import wire_transfer
|
||||
from taler.util.amount import Amount
|
||||
import getpass
|
||||
import uuid
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
LOGGER.setLevel(logging.INFO)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Add bank accounts."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"accountname", type=str, help="Login name of the new bank account"
|
||||
)
|
||||
parser.add_argument(
|
||||
"password", type=str, help="New plain text password of the bank account"
|
||||
)
|
||||
|
||||
##
|
||||
# Django-specific definition to invoke the account creator
|
||||
# @a make_account; it iterates over the list of basic accounts
|
||||
# (defined in the settings) and invoke the account creator
|
||||
# for each one of them.
|
||||
def handle(self, *args, **options):
|
||||
accountname = options["accountname"]
|
||||
password = options["password"]
|
||||
try:
|
||||
existing_user = User.objects.get(username=accountname)
|
||||
existing_user.set_password(password)
|
||||
existing_user.save()
|
||||
except User.DoesNotExist:
|
||||
print(f"Account {accountname} does not exist")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(f"Password for {accountname} changed")
|
|
@ -0,0 +1,52 @@
|
|||
##
|
||||
# This file is part of TALER
|
||||
# (C) 2014, 2015, 2106 Taler Systems SA
|
||||
#
|
||||
# TALER 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,
|
||||
# or (at your option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not,
|
||||
# see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# @author Marcello Stanisci
|
||||
# @author Florian Dold
|
||||
# @brief Create the basic accounts to make the demo bank work.
|
||||
|
||||
import sys
|
||||
import logging
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.utils import ProgrammingError, OperationalError
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
from ...models import BankAccount
|
||||
from ...views import wire_transfer
|
||||
from taler.util.amount import Amount
|
||||
import getpass
|
||||
import uuid
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
LOGGER.setLevel(logging.INFO)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "List bank accounts"
|
||||
|
||||
##
|
||||
# Django-specific definition to invoke the account creator
|
||||
# @a make_account; it iterates over the list of basic accounts
|
||||
# (defined in the settings) and invoke the account creator
|
||||
# for each one of them.
|
||||
def handle(self, *args, **options):
|
||||
accounts = BankAccount.objects.all().order_by("account_no")
|
||||
for account in accounts:
|
||||
print(
|
||||
f"Account {repr(account.user.username)} balance {account.balance.stringify()}"
|
||||
)
|
|
@ -0,0 +1,77 @@
|
|||
##
|
||||
# This file is part of TALER
|
||||
# (C) 2014, 2015, 2106 Taler Systems SA
|
||||
#
|
||||
# TALER 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,
|
||||
# or (at your option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not,
|
||||
# see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# @author Marcello Stanisci
|
||||
# @author Florian Dold
|
||||
# @brief Create the basic accounts to make the demo bank work.
|
||||
|
||||
import sys
|
||||
import logging
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.utils import ProgrammingError, OperationalError
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
from ...models import BankAccount
|
||||
from ...views import wire_transfer
|
||||
from taler.util.amount import Amount
|
||||
import uuid
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
LOGGER.setLevel(logging.INFO)
|
||||
|
||||
|
||||
##
|
||||
# Create a new bank account.
|
||||
#
|
||||
# @param username the username to associate to this account.
|
||||
def make_account(username):
|
||||
try:
|
||||
User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
LOGGER.info("Creating account for '%s'", username)
|
||||
BankAccount(
|
||||
user=User.objects.create_user(
|
||||
username=username, password=str(uuid.uuid4())
|
||||
),
|
||||
is_public=True,
|
||||
).save()
|
||||
|
||||
except (OperationalError, ProgrammingError):
|
||||
LOGGER.error(
|
||||
"db does not exist, or the project"
|
||||
" is not migrated. Try 'taler-bank-manage"
|
||||
" django migrate' in the latter case.",
|
||||
stack_info=False,
|
||||
exc_info=True,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
##
|
||||
# Django-specific definition to register this command.
|
||||
class Command(BaseCommand):
|
||||
help = "Provide initial user accounts"
|
||||
|
||||
##
|
||||
# Django-specific definition to invoke the account creator
|
||||
# @a make_account; it iterates over the list of basic accounts
|
||||
# (defined in the settings) and invoke the account creator
|
||||
# for each one of them.
|
||||
def handle(self, *args, **options):
|
||||
for username in settings.TALER_PREDEFINED_ACCOUNTS:
|
||||
make_account(username)
|
|
@ -0,0 +1,83 @@
|
|||
##
|
||||
# This file is part of TALER
|
||||
# (C) 2014, 2015, 2106 Taler Systems SA
|
||||
#
|
||||
# TALER 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,
|
||||
# or (at your option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not,
|
||||
# see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# @author Marcello Stanisci
|
||||
# @author Florian Dold
|
||||
# @brief Create the basic accounts to make the demo bank work.
|
||||
|
||||
import sys
|
||||
import logging
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.utils import ProgrammingError, OperationalError
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
from ...models import BankAccount
|
||||
from ...views import wire_transfer
|
||||
from taler.util.amount import Amount
|
||||
import getpass
|
||||
import uuid
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
LOGGER.setLevel(logging.INFO)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Add money to a bank account (and debit the bank's account)."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"user",
|
||||
type=str,
|
||||
metavar="USERNAME",
|
||||
help="User that is getting credited with the top-up",
|
||||
)
|
||||
parser.add_argument(
|
||||
"amount",
|
||||
type=str,
|
||||
metavar="AMOUNT",
|
||||
help="Wire transfer's amount, given in the " "CURRENCY:X.Y form.",
|
||||
)
|
||||
|
||||
##
|
||||
# Django-specific definition to invoke the account creator
|
||||
# @a make_account; it iterates over the list of basic accounts
|
||||
# (defined in the settings) and invoke the account creator
|
||||
# for each one of them.
|
||||
def handle(self, *args, **options):
|
||||
user = User.objects.get(username=options["user"])
|
||||
# Take the money from the bank's account
|
||||
try:
|
||||
debit_account = BankAccount.objects.get(
|
||||
account_no=1,
|
||||
)
|
||||
except BankAccount.DoesNotExist:
|
||||
LOGGER.error("Debit account (bank's own account) does not exist.")
|
||||
sys.exit(1)
|
||||
try:
|
||||
amount = Amount.parse(options["amount"])
|
||||
except BadFormatAmount:
|
||||
LOGGER.error("Amount's format is wrong: respect C:X.Y.")
|
||||
sys.exit(1)
|
||||
try:
|
||||
transaction = wire_transfer(
|
||||
amount, debit_account, user.bankaccount, "manual top-up by admin"
|
||||
)
|
||||
print("Transaction id: " + str(transaction.id))
|
||||
except Exception as exc:
|
||||
LOGGER.error(exc)
|
||||
sys.exit(1)
|
|
@ -0,0 +1,106 @@
|
|||
##
|
||||
# This file is part of TALER
|
||||
# (C) 2014, 2015, 2016 Taler Systems SA
|
||||
#
|
||||
# TALER 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, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not, see
|
||||
# <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# @author Marcello Stanisci
|
||||
# @brief CLI utility that issues a wire transfer.
|
||||
|
||||
import sys
|
||||
import logging
|
||||
import json
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.contrib.auth import authenticate
|
||||
from taler.util.amount import Amount
|
||||
from ...views import wire_transfer, User
|
||||
from ...models import BankAccount, BankTransaction
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
##
|
||||
# Django-specific definition to register the CLI utility.
|
||||
class Command(BaseCommand):
|
||||
help = "Wire transfer money and return the transaction id."
|
||||
|
||||
##
|
||||
# Register the command line options of this command.
|
||||
#
|
||||
# @param self this object.
|
||||
# @param parser API used to actually register the option.
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"user",
|
||||
type=str,
|
||||
metavar="USERNAME",
|
||||
help="Which user is performing the wire transfer",
|
||||
)
|
||||
parser.add_argument(
|
||||
"password", type=str, metavar="PASSWORD", help="Performing user's password."
|
||||
)
|
||||
parser.add_argument(
|
||||
"credit-account",
|
||||
type=str,
|
||||
metavar="CREDIT-ACCOUNT",
|
||||
help="Which account will receive money.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"subject",
|
||||
type=str,
|
||||
metavar="SUBJECT",
|
||||
help="SUBJECT will be the wire transfer subject.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"amount",
|
||||
type=str,
|
||||
metavar="AMOUNT",
|
||||
help="Wire transfer's amount, given in the " "CURRENCY:X.Y form.",
|
||||
)
|
||||
|
||||
##
|
||||
# This callable gets invoked when the user invokes the
|
||||
# CLI utility; it is responsible of making the wire transfer
|
||||
# effective.
|
||||
#
|
||||
# @param self this object.
|
||||
# @param args arguments list -- currently unused.
|
||||
# @param options options given by the user at the command line.
|
||||
def handle(self, *args, **options):
|
||||
user = authenticate(username=options["user"], password=options["password"])
|
||||
if not user:
|
||||
LOGGER.error("Wrong user/password.")
|
||||
sys.exit(1)
|
||||
try:
|
||||
amount = Amount.parse(options["amount"])
|
||||
except BadFormatAmount:
|
||||
LOGGER.error("Amount's format is wrong: respect C:X.Y.")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
credit_account_user = User.objects.get(username=options["credit-account"])
|
||||
credit_account = credit_account_user.bankaccount
|
||||
except BankAccount.DoesNotExist:
|
||||
LOGGER.error("Credit account does not exist.")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
transaction = wire_transfer(
|
||||
amount, user.bankaccount, credit_account, options["subject"]
|
||||
)
|
||||
print("Transaction id: " + str(transaction.id))
|
||||
except Exception as exc:
|
||||
LOGGER.error(exc)
|
||||
sys.exit(1)
|
|
@ -0,0 +1,106 @@
|
|||
##
|
||||
# This file is part of TALER
|
||||
# (C) 2014, 2015, 2016 Taler Systems SA
|
||||
#
|
||||
# TALER 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, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not, see
|
||||
# <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# @author Marcello Stanisci
|
||||
# @brief CLI utility to make wire transfers.
|
||||
|
||||
import sys
|
||||
import logging
|
||||
import json
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.contrib.auth import authenticate
|
||||
from taler.util.amount import Amount, AmountFormatError
|
||||
from taler.util.payto import PaytoParse, PaytoFormatError
|
||||
from ...views import wire_transfer, User
|
||||
from ...models import BankAccount, BankTransaction
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
##
|
||||
# Django-specific definition to register the CLI utility.
|
||||
class Command(BaseCommand):
|
||||
help = "Wire transfer money and return the transaction id."
|
||||
|
||||
##
|
||||
# Register the command line options of this command.
|
||||
#
|
||||
# @param self this object.
|
||||
# @param parser API used to actually register the option.
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"user",
|
||||
type=str,
|
||||
metavar="USERNAME",
|
||||
help="Which user is performing the wire transfer",
|
||||
)
|
||||
parser.add_argument(
|
||||
"password", type=str, metavar="PASSWORD", help="Performing user's password."
|
||||
)
|
||||
parser.add_argument(
|
||||
"payto-credit-account-with-subject",
|
||||
type=str,
|
||||
metavar="PAYTO-CREDIT-ACCOUNT-WITH-SUBJECT",
|
||||
help="Which account will receive money, in the form 'payto://x-taler-bank/[bank-host/]CreditAccountName?subject=PaymentSubject'.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"amount",
|
||||
type=str,
|
||||
metavar="AMOUNT",
|
||||
help="Wire transfer's amount, given in the " "CURRENCY:X.Y form.",
|
||||
)
|
||||
|
||||
##
|
||||
# This callable gets invoked when the user invokes the
|
||||
# CLI utility; it is responsible of making the wire transfer
|
||||
# effective.
|
||||
#
|
||||
# @param self this object.
|
||||
# @param args arguments list -- currently unused.
|
||||
# @param options options given by the user at the command line.
|
||||
def handle(self, *args, **options):
|
||||
user = authenticate(username=options["user"], password=options["password"])
|
||||
if not user:
|
||||
LOGGER.error("Wrong user/password.")
|
||||
sys.exit(1)
|
||||
try:
|
||||
amount = Amount.parse(options["amount"])
|
||||
except AmountFormatError:
|
||||
print("Amount format is wrong: respect C:X.Y.")
|
||||
sys.exit(1)
|
||||
try:
|
||||
parsed_payto = PaytoParse(options["payto-credit-account-with-subject"])
|
||||
credit_account_user = User.objects.get(username=parsed_payto.target)
|
||||
credit_account = credit_account_user.bankaccount
|
||||
except User.DoesNotExist:
|
||||
print("Credit account does not exist.")
|
||||
sys.exit(1)
|
||||
except PaytoFormatError as e:
|
||||
print(e)
|
||||
sys.exit(1)
|
||||
if not parsed_payto.message:
|
||||
print("Please provide 'message' parameter along the payto URI")
|
||||
sys.exit(1)
|
||||
try:
|
||||
transaction = wire_transfer(
|
||||
amount, user.bankaccount, credit_account, parsed_payto.message
|
||||
)
|
||||
print("Transaction id: " + str(transaction.id))
|
||||
except Exception as exc:
|
||||
LOGGER.error(exc)
|
||||
sys.exit(1)
|
|
@ -0,0 +1,121 @@
|
|||
import traceback
|
||||
import logging
|
||||
import zlib
|
||||
from . import urls
|
||||
from django.http import JsonResponse
|
||||
from django.urls import reverse
|
||||
from django.shortcuts import redirect
|
||||
from .models import BankAccount, BankTransaction
|
||||
from .views import (
|
||||
DebitLimitException,
|
||||
SameAccountException,
|
||||
LoginFailed,
|
||||
UnhandledException,
|
||||
set_session_hint,
|
||||
)
|
||||
|
||||
from .schemas import JSONFieldException, URLParamValidationError, InvalidSession
|
||||
|
||||
from taler.util.amount import CurrencyMismatchError, AmountFormatError
|
||||
from taler.util.taler_error_codes import ErrorCode
|
||||
from http import HTTPStatus
|
||||
|
||||
LOGGER = logging.getLogger()
|
||||
|
||||
|
||||
##
|
||||
# Class decompressing requests.
|
||||
class DecompressionMiddleware:
|
||||
|
||||
##
|
||||
# Init constructor.
|
||||
#
|
||||
# @param self the object itself.
|
||||
# @param get_response a Django-provided callable that calls
|
||||
# whatever comes next in the chain: a further middleware
|
||||
# or the view itself (please refer to the official
|
||||
# documentation for more details).
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
##
|
||||
# This function is transparently invoked by Django when
|
||||
# a request traverses the chain made of middleware classes
|
||||
# and the view itself as the last element in the chain.
|
||||
#
|
||||
# Here happens the decompression.
|
||||
#
|
||||
# @param self this class.
|
||||
# @param request Django-specific request object (of the same
|
||||
# type that is handed to views).
|
||||
# @return Django-specific response object.
|
||||
def __call__(self, request):
|
||||
if "deflate" == request.META.get("HTTP_CONTENT_ENCODING"):
|
||||
request._body = zlib.decompress(request.body)
|
||||
|
||||
return self.get_response(request)
|
||||
|
||||
|
||||
class ExceptionMiddleware:
|
||||
"""
|
||||
Middleware for handling exceptions not caught directly
|
||||
by the application logic.
|
||||
"""
|
||||
|
||||
def __init__(self, get_response):
|
||||
"""
|
||||
# Init constructor.
|
||||
#
|
||||
# @param self the object itself.
|
||||
# @param get_response a Django-provided callable that calls
|
||||
# whatever comes next in the chain: a further middleware
|
||||
# or the view itself (please refer to the official
|
||||
# documentation for more details).
|
||||
"""
|
||||
self.get_response = get_response
|
||||
|
||||
# Map between endpoints and Web pages to render
|
||||
# after the exception gets managed.
|
||||
self.render = {
|
||||
reverse("profile", urlconf=urls): "profile",
|
||||
reverse("register", urlconf=urls): "index",
|
||||
reverse("public-accounts", urlconf=urls): "index",
|
||||
}
|
||||
|
||||
def __call__(self, request):
|
||||
"""
|
||||
This function is transparently invoked by Django when
|
||||
a request traverses the chain made of middleware classes
|
||||
and the view itself as the last element in the chain.
|
||||
"""
|
||||
return self.get_response(request)
|
||||
|
||||
def process_exception(self, request, exception):
|
||||
"""
|
||||
Main logic for processing the exception. It checks
|
||||
if the exception captured can be managed, and does it
|
||||
if so. Otherwise, it lets the native handler operate.
|
||||
"""
|
||||
LOGGER.error(f"Error: {exception}, while serving {request.get_full_path()}")
|
||||
|
||||
if hasattr(exception, "taler_error_code"):
|
||||
render_to = self.render.get(request.path)
|
||||
if not render_to:
|
||||
response = JsonResponse(
|
||||
dict(code=exception.taler_error_code.value, error=exception.hint),
|
||||
status=exception.http_status_code,
|
||||
)
|
||||
response["Access-Control-Allow-Origin"] = "*"
|
||||
return response
|
||||
set_session_hint(request, success=False, hint=exception.hint)
|
||||
return redirect(render_to)
|
||||
else:
|
||||
LOGGER.error(f"Stack trace: {traceback.format_exc()}")
|
||||
return JsonResponse(
|
||||
dict(
|
||||
code=ErrorCode.BANK_UNMANAGED_EXCEPTION,
|
||||
hint="unexpected exception",
|
||||
exception=str(exception),
|
||||
),
|
||||
status=HTTPStatus.INTERNAL_SERVER_ERROR,
|
||||
)
|
|
@ -0,0 +1,113 @@
|
|||
# Generated by Django 3.0.2 on 2020-01-21 15:47
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import talerbank.app.models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="BankAccount",
|
||||
fields=[
|
||||
("is_public", models.BooleanField(default=False)),
|
||||
("account_no", models.AutoField(primary_key=True, serialize=False)),
|
||||
(
|
||||
"balance",
|
||||
talerbank.app.models.SignedAmountField(
|
||||
default=talerbank.app.models.get_zero_signed_amount
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="TalerWithdrawOperation",
|
||||
fields=[
|
||||
(
|
||||
"withdraw_id",
|
||||
models.UUIDField(
|
||||
default=uuid.uuid4,
|
||||
editable=False,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
("amount", talerbank.app.models.AmountField(default=False)),
|
||||
("selection_done", models.BooleanField(default=False)),
|
||||
("confirmation_done", models.BooleanField(default=False)),
|
||||
("aborted", models.BooleanField(default=False)),
|
||||
("selected_reserve_pub", models.TextField(null=True)),
|
||||
(
|
||||
"selected_exchange_account",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="selected_exchange_account",
|
||||
to="app.BankAccount",
|
||||
),
|
||||
),
|
||||
(
|
||||
"withdraw_account",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="withdraw_account",
|
||||
to="app.BankAccount",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="BankTransaction",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("amount", talerbank.app.models.AmountField(default=False)),
|
||||
(
|
||||
"subject",
|
||||
models.CharField(default="(no subject given)", max_length=200),
|
||||
),
|
||||
("date", models.DateTimeField(auto_now=True, db_index=True)),
|
||||
("cancelled", models.BooleanField(default=False)),
|
||||
("request_uid", models.CharField(max_length=128, unique=True)),
|
||||
(
|
||||
"credit_account",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="credit_account",
|
||||
to="app.BankAccount",
|
||||
),
|
||||
),
|
||||
(
|
||||
"debit_account",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="debit_account",
|
||||
to="app.BankAccount",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -0,0 +1,216 @@
|
|||
##
|
||||
# This file is part of TALER
|
||||
# (C) 2014, 2015, 2016 Taler Systems SA
|
||||
#
|
||||
# TALER 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, or
|
||||
# (at your option) any later version. TALER 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 TALER; see the file COPYING. If not, see
|
||||
# <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# @author Marcello Stanisci
|
||||
# @author Florian Dold
|
||||
|
||||
import uuid
|
||||
from typing import Any, Tuple
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError, ObjectDoesNotExist
|
||||
from taler.util.amount import Amount, SignedAmount, CurrencyMismatchError
|
||||
|
||||
|
||||
def get_zero_amount() -> Amount:
|
||||
"""
|
||||
Helper function that instantiates a zero-valued Amount
|
||||
object in the currency that the bank runs on.
|
||||
"""
|
||||
return Amount(settings.TALER_CURRENCY, 0, 0)
|
||||
|
||||
|
||||
def get_zero_signed_amount() -> SignedAmount:
|
||||
"""
|
||||
Helper function that instantiates a zero-valued SignedAmount
|
||||
object in the currency that the bank runs on.
|
||||
"""
|
||||
return SignedAmount(True, get_zero_amount())
|
||||
|
||||
|
||||
class SignedAmountField(models.Field):
|
||||
"""Custom implementation of the SignedAmount class as a database type."""
|
||||
|
||||
description = "Signed amount object in Taler style"
|
||||
|
||||
def db_type(self, connection: Any) -> str:
|
||||
"""
|
||||
Return the database type of the serialized amount.
|
||||
"""
|
||||
return "varchar"
|
||||
|
||||
def get_prep_value(self, value: SignedAmount) -> str:
|
||||
"""
|
||||
Stringifies the Amount object to feed the DB connector.
|
||||
"""
|
||||
c = value.amount.currency
|
||||
if settings.TALER_CURRENCY != c:
|
||||
raise CurrencyMismatchError(settings.TALER_CURRENCY, c)
|
||||
return value.stringify()
|
||||
|
||||
@staticmethod
|
||||
def from_db_value(value: str, *args) -> Amount:
|
||||
"""
|
||||
Parse the stringified Amount back to Python.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
value : str
|
||||
Serialized amount coming from the database.
|
||||
(String in the usual CURRENCY:X.Y format)
|
||||
args : any
|
||||
Unused
|
||||
"""
|
||||
del args # pacify PEP checkers
|
||||
return SignedAmount.parse(value)
|
||||
|
||||
def to_python(self, value: Any) -> Amount:
|
||||
"""
|
||||
Parse the stringified Amount back to Python. FIXME:
|
||||
why this serializer consider _more_ cases respect to the
|
||||
one above ('from_db_value')?
|
||||
|
||||
Parameters
|
||||
----------
|
||||
value: serialized amount coming from the database
|
||||
|
||||
"""
|
||||
|
||||
if isinstance(value, SignedAmount):
|
||||
return value
|
||||
try:
|
||||
return SignedAmount.parse(value)
|
||||
except BadFormatAmount:
|
||||
raise ValidationError(
|
||||
"Invalid input for a signed amount string: %s" % value
|
||||
)
|
||||
|
||||
|
||||
class AmountField(models.Field):
|
||||
"""Custom implementation of the Amount class as a database type."""
|
||||
|
||||
description = "Amount object in Taler style"
|
||||
|
||||
def db_type(self, connection: Any) -> str:
|
||||
"""
|
||||
Return the database type of the serialized amount.
|
||||
"""
|
||||
return "varchar"
|
||||
|
||||
def get_prep_value(self, value: Amount) -> str:
|
||||
"""
|
||||
Stringifies the Amount object to feed the DB connector.
|
||||
"""
|
||||
if settings.TALER_CURRENCY != value.currency:
|
||||
raise CurrencyMismatchError(settings.TALER_CURRENCY, value.currency)
|
||||
return value.stringify()
|
||||
|
||||
@staticmethod
|
||||
def from_db_value(value: str, *args) -> Amount:
|
||||
"""
|
||||
Parse the stringified Amount back to Python.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
value : str
|
||||
Serialized amount coming from the database.
|
||||
(String in the usual CURRENCY:X.Y format)
|
||||
args : any
|
||||
Unused
|
||||
"""
|
||||
del args # pacify PEP checkers
|
||||
return Amount.parse(value)
|
||||
|
||||
def to_python(self, value: Any) -> Amount:
|
||||
"""
|
||||
Parse the stringified Amount back to Python. FIXME:
|
||||
why this serializer consider _more_ cases respect to the
|
||||
one above ('from_db_value')?
|
||||
|
||||
Parameters
|
||||
----------
|
||||
value: serialized amount coming from the database
|
||||
|
||||
"""
|
||||
|
||||
if isinstance(value, Amount):
|
||||
return value
|
||||
try:
|
||||
return Amount.parse(value)
|
||||
except BadFormatAmount:
|
||||
raise ValidationError("Invalid input for an amount string: %s" % value)
|
||||
|
||||
|
||||
def join_dict(**inputDict):
|
||||
return ", ".join(["%s==%s" % (key, value) for (key, value) in inputDict.items()])
|
||||
|
||||
|
||||
class BankAccount(models.Model):
|
||||
"""
|
||||
The class representing a bank account.
|
||||
"""
|
||||
|
||||
is_public = models.BooleanField(default=False)
|
||||
account_no = models.AutoField(primary_key=True)
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||
balance = SignedAmountField(default=get_zero_signed_amount)
|
||||
|
||||
|
||||
class BankTransaction(models.Model):
|
||||
"""
|
||||
The class representing a bank transaction.
|
||||
"""
|
||||
|
||||
amount = AmountField(default=False)
|
||||
debit_account = models.ForeignKey(
|
||||
BankAccount,
|
||||
on_delete=models.CASCADE,
|
||||
db_index=True,
|
||||
related_name="debit_account",
|
||||
)
|
||||
credit_account = models.ForeignKey(
|
||||
BankAccount,
|
||||
on_delete=models.CASCADE,
|
||||
db_index=True,
|
||||
related_name="credit_account",
|
||||
)
|
||||
subject = models.CharField(default="(no subject given)", max_length=200)
|
||||
date = models.DateTimeField(auto_now=True, db_index=True)
|
||||
cancelled = models.BooleanField(default=False)
|
||||
request_uid = models.CharField(max_length=128, unique=True)
|
||||
|
||||
|
||||
class TalerWithdrawOperation(models.Model):
|
||||
withdraw_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
amount = AmountField(default=False)
|
||||
withdraw_account = models.ForeignKey(
|
||||
BankAccount,
|
||||
on_delete=models.CASCADE,
|
||||
db_index=True,
|
||||
related_name="withdraw_account",
|
||||
)
|
||||
selection_done = models.BooleanField(default=False)
|
||||
confirmation_done = models.BooleanField(default=False)
|
||||
aborted = models.BooleanField(default=False)
|
||||
selected_exchange_account = models.ForeignKey(
|
||||
BankAccount,
|
||||
null=True,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="selected_exchange_account",
|
||||
)
|
||||
selected_reserve_pub = models.TextField(null=True)
|
|
@ -0,0 +1,259 @@
|
|||
##
|
||||
# This file is part of TALER
|
||||
# (C) 2014, 2015, 2016, 2020 Taler Systems SA
|
||||
#
|
||||
# TALER 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, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not, see
|
||||
# <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# @author Marcello Stanisci
|
||||
# @brief definitions of JSON schemas for validating data
|
||||
|
||||
import json
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django import forms
|
||||
from django.core.validators import RegexValidator
|
||||
from urllib.parse import urlparse
|
||||
from taler.util.taler_error_codes import ErrorCode
|
||||
from http import HTTPStatus
|
||||
|
||||
##
|
||||
# Constant value for the biggest number the bank handles.
|
||||
# This value is just equal to the biggest number that JavaScript
|
||||
# can handle (because of the wallet).
|
||||
# FIXME: also defined in views.py. Need a common.py to contain
|
||||
# such definitions ?
|
||||
UINT64_MAX = (2 ** 64) - 1
|
||||
|
||||
##
|
||||
# Pattern for amounts, plain RegEx.
|
||||
AMOUNT_REGEX = "^[A-Za-z0-9_-]+:([0-9]+)\.?([0-9]+)?$"
|
||||
|
||||
|
||||
##
|
||||
# Exception class to be raised when a expected URL parameter
|
||||
# is not found.
|
||||
class InvalidSession(ValueError):
|
||||
##
|
||||
# Init method.
|
||||
#
|
||||
# @param self the object itself.
|
||||
# @param http_status_code the HTTP response code to return
|
||||
# to the caller (client).
|
||||
def __init__(self, http_status_code):
|
||||
self.hint = "Landed on a broken session"
|
||||
self.http_status_code = http_status_code
|
||||
super().__init__()
|
||||
|
||||
|
||||
class InternalServerError(Exception):
|
||||
def __init__(self, hint):
|
||||
self.hint = hint
|
||||
self.http_status_code = HTTPStatus.INTERNAL_SERVER_ERROR
|
||||
self.taler_error_code = ErrorCode.INTERNAL_LOGIC_ERROR
|
||||
|
||||
|
||||
##
|
||||
# Exception class to be raised when a JSON
|
||||
# object does not respect a specification.
|
||||
class JSONFieldException(ValueError):
|
||||
|
||||
##
|
||||
# Init method.
|
||||
#
|
||||
# @param self the object itself.
|
||||
# @param error object containing the hint, as created by
|
||||
# the Form API.
|
||||
# @param http_status_code the HTTP response code to return
|
||||
# to the caller (client).
|
||||
def __init__(self, error, http_status_code):
|
||||
for k, errors in error.as_data().items():
|
||||
messages = [", ".join(error.messages) for error in errors]
|
||||
line = f"{k}: " + "".join(messages)
|
||||
super(JSONFieldException, self).__init__(line)
|
||||
self.hint = line
|
||||
self.http_status_code = http_status_code
|
||||
self.taler_error_code = TalerErrorCode.BANK_JSON_INVALID
|
||||
|
||||
|
||||
##
|
||||
# Exception class to be raised when at least one expected URL
|
||||
# parameter is either not found or malformed.
|
||||
class URLParamValidationError(ValueError):
|
||||
##
|
||||
# Init method.
|
||||
#
|
||||
# @param self the object itself.
|
||||
# @param error object containing the hint.
|
||||
# @param http_status_code the HTTP response code to return
|
||||
# to the caller (client).
|
||||
def __init__(self, error, http_status_code):
|
||||
self.hint = json.stringify(error.as_json())
|
||||
self.http_status_code = http_status_code
|
||||
self.taler_error_code = ErrorCode.BANK_PARAMETER_MISSING_OR_INVALID
|
||||
super().__init__()
|
||||
|
||||
|
||||
class AuthForm(forms.Form):
|
||||
type = forms.CharField(
|
||||
validators=[
|
||||
RegexValidator("^basic$", message="Only 'basic' method provided for now")
|
||||
]
|
||||
)
|
||||
|
||||
data = forms.Field(required=False)
|
||||
|
||||
|
||||
class AuthField(forms.Field):
|
||||
##
|
||||
# No need to touch the input. Dict is good
|
||||
# and gets validated by the "validate()" method.
|
||||
def to_python(self, value):
|
||||
return value
|
||||
|
||||
##
|
||||
# Validate input.
|
||||
def validate(self, value):
|
||||
af = AuthForm(value)
|
||||
if not af.is_valid():
|
||||
raise ValidationError(json.dumps(af.errors.as_json()))
|
||||
|
||||
|
||||
##
|
||||
# Common logic to inherit from all the other validators
|
||||
class BankValidator:
|
||||
def __init__(self, validator, data):
|
||||
self.validation_result = validator(data)
|
||||
if not self.validation_result.is_valid():
|
||||
raise JSONFieldException(
|
||||
self.validation_result.errors, HTTPStatus.BAD_REQUEST
|
||||
)
|
||||
|
||||
def get(self, name, default=None):
|
||||
ret = self.validation_result.cleaned_data.get(name)
|
||||
if not ret:
|
||||
return default
|
||||
return ret
|
||||
|
||||
|
||||
class AddIncomingData(BankValidator):
|
||||
def __init__(self, data):
|
||||
super(AddIncomingData, self).__init__(self.InnerValidator, data)
|
||||
|
||||
class InnerValidator(forms.Form):
|
||||
amount = forms.CharField(
|
||||
validators=[
|
||||
RegexValidator(
|
||||
AMOUNT_REGEX, message="Format CURRENCY:X[.Y] not respected"
|
||||
)
|
||||
]
|
||||
)
|
||||
subject = forms.CharField()
|
||||
credit_account = forms.IntegerField(min_value=1)
|
||||
exchange_url = forms.URLField()
|
||||
|
||||
|
||||
##
|
||||
# Subset of /history and /history-range input.
|
||||
class HistoryParamsBase(forms.Form):
|
||||
cancelled = forms.CharField(
|
||||
required=False,
|
||||
empty_value="show",
|
||||
validators=[
|
||||
RegexValidator("^(omit|show)$", message="Only 'omit' or 'show' are valid")
|
||||
],
|
||||
)
|
||||
|
||||
ordering = forms.CharField(
|
||||
required=False,
|
||||
empty_value="descending",
|
||||
validators=[
|
||||
RegexValidator(
|
||||
"^(ascending|descending)$",
|
||||
message="Only 'ascending' or 'descending' are valid",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
direction = forms.CharField(
|
||||
validators=[
|
||||
RegexValidator(
|
||||
"^(debit|credit|both|cancel\+|cancel-)$",
|
||||
message="Only: debit/credit/both/cancel+/cancel-",
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
# FIXME: adjust min/max values.
|
||||
account_number = forms.IntegerField(required=False)
|
||||
|
||||
|
||||
class HistoryParams(BankValidator):
|
||||
def __init__(self, data):
|
||||
super(HistoryParams, self).__init__(self.InnerValidator, data)
|
||||
|
||||
class InnerValidator(HistoryParamsBase):
|
||||
# FIXME: adjust min/max values.
|
||||
delta = forms.IntegerField()
|
||||
start = forms.IntegerField(required=False)
|
||||
|
||||
|
||||
class PaytoField(forms.Field):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def to_python(self, value):
|
||||
return value
|
||||
|
||||
def validate(self, value):
|
||||
|
||||
# The request misses this, default exchange
|
||||
# will be used. NOTE: experience showed that the
|
||||
# "required=False" argument given when init the object
|
||||
# does NOT prevent this function from being called!
|
||||
if not value:
|
||||
return
|
||||
wire_uri = urlparse(value)
|
||||
if "payto" != wire_uri.scheme:
|
||||
raise ValidationError("URL is not 'payto'")
|
||||
|
||||
|
||||
class WithdrawHeadless(BankValidator):
|
||||
def __init__(self, data):
|
||||
super(WithdrawHeadless, self).__init__(self.InnerValidator, data)
|
||||
|
||||
class InnerValidator(forms.Form):
|
||||
amount = forms.CharField(
|
||||
validators=[
|
||||
RegexValidator(
|
||||
AMOUNT_REGEX, message="Format CURRENCY:X[.Y] not respected"
|
||||
)
|
||||
]
|
||||
)
|
||||
reserve_pub = forms.CharField(required=True)
|
||||
exchange_payto_uri = PaytoField(required=True)
|
||||
|
||||
|
||||
class WithdrawHeadlessUri(BankValidator):
|
||||
def __init__(self, data):
|
||||
super(WithdrawHeadlessUri, self).__init__(self.InnerValidator, data)
|
||||
|
||||
class InnerValidator(forms.Form):
|
||||
amount = forms.CharField(
|
||||
validators=[
|
||||
RegexValidator(
|
||||
AMOUNT_REGEX, message="Format CURRENCY:X[.Y] not respected"
|
||||
)
|
||||
]
|
||||
)
|
|
@ -0,0 +1,80 @@
|
|||
.abort-button {
|
||||
margin-left: 2px;
|
||||
border: 2px solid rgb(0, 120, 231);
|
||||
color: rgb(0, 120, 231);
|
||||
font-size: 87%;
|
||||
margin-top: 1px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
div.pages-list {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
a.page-number {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
a.current-page-number {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.cancelled {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
input[type="number"]::-webkit-outer-spin-button,
|
||||
input[type="number"]::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
#transfer-fields {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#id_amount {
|
||||
width: 6em;
|
||||
display: inline-block;
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Amount without the currency,
|
||||
* placed left to a .currency-indicator.
|
||||
*/
|
||||
#main .amount {
|
||||
width: 6em;
|
||||
display: inline-block;
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Currency indicator to the right of input fields,
|
||||
* with non-rounded corners to the left.
|
||||
*/
|
||||
#main .currency-indicator {
|
||||
color: black;
|
||||
display: inline-block;
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
}
|
||||
|
||||
#main .fieldlabel {
|
||||
display: block;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
#main .fieldbox {
|
||||
margin-right: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
#logout-button {
|
||||
display: block;
|
||||
width: fit-content;
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
@charset "UTF-8";
|
||||
/*
|
||||
Style common to all demo pages.
|
||||
|
||||
Colors:
|
||||
- #1e2739 (dark blue)
|
||||
- #0042b2 (default blue)
|
||||
- #3daee9 (highlight blue)
|
||||
*/
|
||||
|
||||
.demobar h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.demobar > p {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.demobar a,
|
||||
.demobar a:visited {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.tt {
|
||||
font-family: "Lucida Console", Monaco, monospace;
|
||||
}
|
||||
|
||||
.informational-ok {
|
||||
background: lightgreen;
|
||||
border-radius: 1em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.informational-fail {
|
||||
background: lightpink;
|
||||
border-radius: 1em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-left: 2em;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.demobar {
|
||||
overflow-x: auto;
|
||||
background-color: #0042b2;
|
||||
color: white;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.navcontainer {
|
||||
background: #0042b2;
|
||||
margin-bottom: 50px;
|
||||
width: 100%;
|
||||
color: white;
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
width: 100vw;
|
||||
backdrop-filter: blur(10px);
|
||||
opacity: 1;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
nav {
|
||||
left: 1vw;
|
||||
position: relative;
|
||||
background: #0042b2;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
nav a,
|
||||
nav span,
|
||||
.navbtn {
|
||||
border: none;
|
||||
color: white;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
background: #0042b2;
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
nav a,
|
||||
nav span,
|
||||
.navbtn {
|
||||
padding: 15px 32px;
|
||||
}
|
||||
|
||||
nav a:hover,
|
||||
nav span:hover,
|
||||
.navbtn:hover {
|
||||
background: #3daee9;
|
||||
}
|
||||
|
||||
nav a.active,
|
||||
nav span.active,
|
||||
.navbtn.active {
|
||||
background-color: #1e2739;
|
||||
}
|
||||
|
||||
nav a.active:hover,
|
||||
nav span.active:hover,
|
||||
.navbtn.active:hover {
|
||||
background: #3daee9;
|
||||
}
|
||||
|
||||
nav a,
|
||||
nav span,
|
||||
.navbtn {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
nav .right {
|
||||
float: right;
|
||||
margin-right: 5vw;
|
||||
}
|
||||
nav .right div.nav {
|
||||
display: none;
|
||||
}
|
||||
nav .right div.nav:hover {
|
||||
display: block;
|
||||
}
|
||||
|
||||
nav .right:hover div.nav {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.langbtn {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
a[disabled="true"] {
|
||||
pointer-events: none;
|
||||
color: grey;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="670"
|
||||
height="300"
|
||||
viewBox="0 0 201 90"
|
||||
version="1.1"
|
||||
id="svg8">
|
||||
<g
|
||||
id="logo">
|
||||
<g
|
||||
id="circles"
|
||||
style="fill:#FFF;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.327943">
|
||||
<path
|
||||
d="m 86.662153,1.1211936 c 15.589697,0 29.129227,9.4011664 35.961027,23.2018054 h -5.81736 C 110.4866,13.623304 99.349002,6.5180852 86.662153,6.5180852 c -19.690571,0 -35.652876,17.1120008 -35.652876,38.2205688 0,10.331797 3.825597,19.704678 10.03957,26.582945 -1.342357,1.120912 -2.771532,2.127905 -4.275488,3.006754 C 50.071485,66.553412 45.974857,56.15992 45.974857,44.738654 c 0,-24.089211 18.216325,-43.6174604 40.687296,-43.6174604 z M 122.51416,65.375898 c -6.86645,13.680134 -20.34561,22.980218 -35.852007,22.980218 -1.052702,0 -2.096093,-0.04291 -3.128683,-0.127026 3.052192,-1.561167 5.913582,-3.480387 8.538307,-5.707305 10.320963,-1.684389 19.185983,-8.113638 24.601813,-17.145887 z"
|
||||
id="path2350" />
|
||||
<path
|
||||
d="m 64.212372,1.1211936 c 1.052607,0 2.095998,0.042919 3.128684,0.1270583 C 64.288864,2.8094199 61.427378,4.728606 58.802653,6.9555572 41.679542,9.7498571 28.559494,25.601563 28.559494,44.738654 c 0,14.264563 7.29059,26.702023 18.093843,33.268925 -1.593656,0.26719 -3.226966,0.406948 -4.890748,0.406948 -1.239545,0 -2.46151,-0.07952 -3.663522,-0.229364 C 29.191129,70.184015 23.525076,58.171633 23.525076,44.738654 23.525076,20.649443 41.7414,1.1211936 64.212372,1.1211936 Z M 69.62209,82.521785 C 79.943207,80.837396 88.808164,74.407841 94.224059,65.375422 h 5.840511 c -6.866354,13.680305 -20.345548,22.980694 -35.852198,22.980694 -1.052703,0 -2.095999,-0.04291 -3.128684,-0.127026 3.052002,-1.561371 5.913836,-3.480218 8.538402,-5.707305 z M 94.355885,24.322999 c -3.13939,-5.314721 -7.467551,-9.74275 -12.584511,-12.853269 1.593656,-0.26719 3.226904,-0.406948 4.890779,-0.406948 1.239451,0 2.461512,0.07952 3.663524,0.229364 4.016018,3.607242 7.373195,8.030111 9.849053,13.030853 z"
|
||||
id="path2352" />
|
||||
<path
|
||||
d="m 41.762589,1.1211936 c 1.064296,0 2.118804,0.044379 3.162607,0.1302161 -3.046523,1.558961 -5.903162,3.4745139 -8.52358,5.6968133 C 19.254624,9.7205882 6.1097128,25.583465 6.1097128,44.738654 c 0,21.108568 15.9624012,38.22057 35.6528762,38.22057 12.599746,0 23.672446,-7.007056 30.013748,-17.583802 h 5.838515 C 70.748498,79.055727 57.26924,88.356116 41.762589,88.356116 c -22.470907,0 -40.6871998,-19.52825 -40.6871998,-43.617462 0,-24.089211 18.2162928,-43.6174604 40.6871998,-43.6174604 z M 71.905375,24.322999 c -1.31192,-2.220567 -2.830984,-4.287049 -4.528877,-6.166508 1.342452,-1.120945 2.771374,-2.128381 4.275139,-3.00723 2.372984,2.753011 4.418875,5.834636 6.072489,9.173738 z"
|
||||
id="path2354" />
|
||||
</g>
|
||||
<g
|
||||
id="letters"
|
||||
style="fill:#FFF">
|
||||
<path
|
||||
d="m 76.135411,34.409066 h 9.161042 V 29.36588 H 61.857537 v 5.043186 h 9.161137 v 25.92317 h 5.116737 z"
|
||||
id="path2346" />
|
||||
<path
|
||||
d="m 92.647571,52.856334 h 13.659009 l 2.93009,7.476072 h 5.36461 L 101.89122,29.144903 H 97.187186 L 84.477089,60.332406 h 5.199533 z m 11.802109,-4.822276 h -9.944771 l 4.951718,-12.386462 z"
|
||||
id="path2362" />
|
||||
<path
|
||||
d="m 123.80641,29.366084 h -4.58038 v 30.966322 h 20.54728 v -4.910253 c -5.32227,0 -10.64463,0 -15.9669,0 z"
|
||||
id="path2356" />
|
||||
<path
|
||||
d="m 166.4722,29.366084 h -21.37564 v 30.966322 h 21.58203 v -4.910253 h -16.54771 v -8.27275 h 14.48439 V 42.23925 h -14.48439 v -7.962811 h 16.34132 z"
|
||||
id="path2360" />
|
||||
<path
|
||||
d="m 191.19035,39.474593 c 0,1.59947 -0.53646,2.87535 -1.61628,3.818883 -1.07281,0.95124 -2.52409,1.422837 -4.34678,1.422837 h -7.44851 V 34.276439 h 7.4073 c 1.9051,0 3.38376,0.435027 4.42939,1.312178 1.05226,0.870258 1.57488,2.167734 1.57488,3.885976 z m 6.06602,20.857813 -7.79911,-11.723191 c 1.01771,-0.294794 1.94631,-0.714813 2.78553,-1.260566 0.83885,-0.545619 1.56122,-1.209263 2.16629,-1.990627 0.60541,-0.781738 1.07981,-1.681096 1.42369,-2.698345 0.34378,-1.017553 0.51561,-2.175238 0.51561,-3.472883 0,-1.50409 -0.24743,-2.867948 -0.74267,-4.092048 -0.49515,-1.223794 -1.20344,-2.256186 -2.12499,-3.096734 -0.92173,-0.840446 -2.04957,-1.489252 -3.38375,-1.946452 -1.33447,-0.457267 -2.82692,-0.685476 -4.4774,-0.685476 h -12.87512 v 30.966322 h 5.03433 V 49.538522 h 6.37569 l 7.11829,10.793884 z"
|
||||
id="path2358" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.5 KiB |
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
@licstart The following is the entire license notice for the
|
||||
JavaScript code in this page.
|
||||
|
||||
Copyright (C) 2014, 2015, 2016 Inria and GNUnet e.V.
|
||||
|
||||
The JavaScript code in this page is free software: you can
|
||||
redistribute it and/or modify it under the terms of the GNU
|
||||
General Public License (GNU GPL) as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option)
|
||||
any later version. The code is distributed WITHOUT ANY WARRANTY;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
|
||||
|
||||
As additional permission under GNU GPL version 3 section 7, you
|
||||
may distribute non-source (e.g., minimized or compacted) forms of
|
||||
that code without the copy of the GNU GPL normally required by
|
||||
section 4, provided you include this license notice and a URL
|
||||
through which recipients can access the Corresponding Source.
|
||||
|
||||
@licend The above is the entire license notice
|
||||
for the JavaScript code in this page. */
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
var bank_currency;
|
||||
var precision;
|
||||
var callback_url;
|
||||
var reserve_pub;
|
||||
var suggested_exchange;
|
||||
|
||||
|
||||
/**
|
||||
* Get a constant stored in the DOM
|
||||
* as a meta tag.
|
||||
*/
|
||||
function getConst(name) {
|
||||
var metas = document.getElementsByTagName("meta");
|
||||
if (!(name in metas)) {
|
||||
return;
|
||||
}
|
||||
return metas[name].getAttribute("value");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse fractional format (e.g. 42.12 EUR) into
|
||||
* Taler amount.
|
||||
*/
|
||||
function parseAmount(amount_str) {
|
||||
var re = /([0-9]+)(\.?[0-9][0-9]?)? ([A-Z]+)/;
|
||||
var amount = re.exec(amount_str);
|
||||
if (amount == null || amount[0] != amount_str){
|
||||
window.alert("Incorrect amount entered, give in the"
|
||||
+ " form 'XY.Z EUR' or 'XY EUR'");
|
||||
return null;
|
||||
}
|
||||
var amount_fraction = 0;
|
||||
if (amount[2] != null) // fractional part given
|
||||
amount_fraction = Number("0." + amount[2]) * 1000000;
|
||||
if (amount[1] + amount_fraction == 0)
|
||||
return null;
|
||||
return {
|
||||
value: Number(amount[1]),
|
||||
fraction: amount_fraction,
|
||||
currency: amount[amount.length - 1]
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
function init() {
|
||||
bank_currency = getConst("currency");
|
||||
precision = getConst("precision");
|
||||
callback_url = getConst("callback-url");
|
||||
reserve_pub = getConst("reserve-pub");
|
||||
suggested_exchange = getConst("suggested-exchange");
|
||||
if (reserve_pub) {
|
||||
console.log("confirming reserve", reserve_pub);
|
||||
taler.confirmReserve(reserve_pub);
|
||||
}
|
||||
document.getElementById("select-exchange").onclick = function () {
|
||||
var form = document.getElementById("reserve-form");
|
||||
var amount = {
|
||||
value: parseInt(form.elements["reserve-amount"].value),
|
||||
fraction: 0,
|
||||
currency: bank_currency
|
||||
};
|
||||
console.log("callback_url", callback_url);
|
||||
taler.createReserve(callback_url, amount, ["test"], suggested_exchange);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
if (document.readyState == "loading") {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
} else {
|
||||
init();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,14 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<h1>{{ _("Error") }}</h1>
|
||||
|
||||
<aside class="sidebar" id="left">
|
||||
</aside>
|
||||
<section id="main">
|
||||
<article>
|
||||
<p>{{ _("Page not found!") }}</p>
|
||||
</article>
|
||||
</section>
|
||||
{% endblock main %}
|
|
@ -0,0 +1,16 @@
|
|||
{% extends "common_base.html" %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" type="text/css" href="{{ static('bank.css') }}" />
|
||||
<link rel="stylesheet" type="text/css" href="{{ static('disabled-button.css') }}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block header_content %}
|
||||
|
||||
<h1><span class="it"><a href="{{ env('TALER_ENV_URL_BANK') }}">{{ gettext("Demo Bank") }}</a></span></h1>
|
||||
|
||||
<p>
|
||||
{{ _("This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some <a href=\"{public_accounts}\">Public Accounts</a>.").format(public_accounts=url('public-accounts')) }}
|
||||
</p>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,93 @@
|
|||
<!DOCTYPE html>
|
||||
<!--
|
||||
This file is part of GNU TALER.
|
||||
Copyright (C) 2014, 2015, 2016, 2020, 2021 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Lesser General Public License as published by the Free Software
|
||||
Foundation; either version 2.1, or (at your option) any later version.
|
||||
|
||||
TALER 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ page_title | default(gettext("GNU Taler Demo")) }}</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ static('pure.css') }}" />
|
||||
<link rel="stylesheet" type="text/css" href="{{ static('demo.css') }}" />
|
||||
{% block head %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header class="demobar" style="display: flex; flex-direction: row; justify-content: space-between;">
|
||||
<div style="max-width: 50em; margin-left: 2em;">
|
||||
{% block header_content %}
|
||||
<p>This is the header content.</p>
|
||||
{% endblock %}
|
||||
</div>
|
||||
<a href="https://taler.net/">
|
||||
<img src="{{ static('logo-white.svg') }}" height="100" width="224" style="margin: 2em 2em"><br/>
|
||||
</a>
|
||||
</header>
|
||||
|
||||
|
||||
<div style="display:flex; flex-direction: column;" class="navcontainer">
|
||||
<nav class="demolist">
|
||||
<a href="{{ env('TALER_ENV_URL_INTRO', '#') + getlang() + '/' }}"
|
||||
{% if getactive() == 'landing' %} class="active" {% endif %}
|
||||
>{{gettext("Introduction")}}</a>
|
||||
<a href="{{ env('TALER_ENV_URL_BANK', '#') + getlang() + '/' }}"
|
||||
{% if getactive() == 'bank' %} class="active" {% endif %}
|
||||
>{{gettext("Bank")}}</a>
|
||||
<a href="{{ env('TALER_ENV_URL_MERCHANT_BLOG', '#') + getlang() + '/' }}"
|
||||
{% if getactive() == 'blog' %} class="active" {% endif %}
|
||||
>{{gettext("Essay Shop")}}</a>
|
||||
<a href="{{ env('TALER_ENV_URL_MERCHANT_DONATIONS', '#') + getlang() + '/' }}"
|
||||
{% if getactive() == 'donations' %} class="active" {% endif %}
|
||||
>{{gettext("Donations")}}</a>
|
||||
<a href="{{ env('TALER_ENV_URL_MERCHANT_SURVEY', '#') + getlang() + '/' }}"
|
||||
{% if getactive() == 'survey' %} class="active" {% endif %}
|
||||
>{{gettext("Tipping/Survey")}}</a>
|
||||
|
||||
{# Language Selector #}
|
||||
<div class="right">
|
||||
<span>{{ all_languages[getlang()] | default("en") | safe }}</span>
|
||||
<div style="position: relative; overflow: visible;">
|
||||
<div class="nav" style="position: absolute; background: #0042b2; max-height: 60vh; overflow-y: scroll">
|
||||
<br>
|
||||
{% for lang_code, lang_display in all_languages.items() %}
|
||||
{% if lang_code != getlang() %}
|
||||
<a href="/{{ lang_code }}/" class="navbtn">{{ lang_display | safe }}</a>
|
||||
<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<section id="main" class="content">
|
||||
{% block main %}
|
||||
This is the main content of the page.
|
||||
{% endblock %}
|
||||
<hr />
|
||||
<div>
|
||||
<p>
|
||||
{{
|
||||
gettext('You can learn more about GNU Taler on our main <a href="{site}">website</a>.').format(site="https://taler.net/" + getlang() + "/")
|
||||
}}
|
||||
</p>
|
||||
<div style="flex-grow:1"></div>
|
||||
<p>Copyright © 2014—2021 Taler Systems SA</p>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,71 @@
|
|||
{% extends "base.html" %}
|
||||
{#
|
||||
This file is part of GNU TALER.
|
||||
Copyright (C) 2014, 2015, 2016 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Lesser General Public License as published by the Free Software
|
||||
Foundation; either version 2.1, or (at your option) any later version.
|
||||
|
||||
TALER 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
@author Marcello Stanisci
|
||||
@author Florian Dold
|
||||
#}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<h1 class="nav"> {{ _("Welcome to the {currency} Bank!").format(currency=settings_value("TALER_CURRENCY")) }}</h1>
|
||||
|
||||
<section id="main">
|
||||
<article>
|
||||
<div class="login-form">
|
||||
<h2>{{ _("Please login!") }}</h2>
|
||||
|
||||
{% if form.errors %}
|
||||
<p class="informational informational-fail">
|
||||
{{ _("Your username and password didn't match. Please try again.") }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if next and next != url('profile') %}
|
||||
{% if request.user and request.user.is_authenticated %}
|
||||
<p class="informational informational-fail">
|
||||
{{ _("Your account doesn't have access to this page. To proceed, please login with an account that has access.") }}</p>
|
||||
{% else %}
|
||||
<p class="informational informational-fail">
|
||||
{{ _("Please login to see this page.") }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<form method="post" class="pure-form" action="{{ url('login') }}">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}" />
|
||||
{{ form.username }}
|
||||
<input type="password" name="password" placeholder="password" />
|
||||
<input type="submit" value="login" class="pure-button pure-button-primary" />
|
||||
<input type="hidden" name="next" value="{{ next }}" />
|
||||
</form>
|
||||
</div>
|
||||
{% if settings_value("ALLOW_REGISTRATIONS") %}
|
||||
<p>
|
||||
{% autoescape off %}
|
||||
{{ _("If you are a new customer please <a href=\"{register_link}\">register</a>. Registration is fast and free, and it gives you a registration bonus of 100 {currency}").format(register_link=url('register'), currency=settings_value("TALER_CURRENCY")) }}
|
||||
{% endautoescape %}
|
||||
</p>
|
||||
{% else %}
|
||||
<p>{{ _("Registrations are not open to the public.") }}</p>
|
||||
{% endif %}
|
||||
<p>
|
||||
{% autoescape off %}
|
||||
{{ _("To view transactions of public accounts, please <a href=\"{public_accounts}\">click here</a>.").format(public_accounts=url('public-accounts')) }}
|
||||
{% endautoescape %}
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
{% endblock main %}
|
|
@ -0,0 +1,66 @@
|
|||
{% extends "base.html" %}
|
||||
{#
|
||||
This file is part of GNU TALER.
|
||||
Copyright (C) 2014, 2015, 2016 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Lesser General Public License as published by the Free Software
|
||||
Foundation; either version 2.1, or (at your option) any later version.
|
||||
|
||||
TALER 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
@author Marcello Stanisci
|
||||
@author Florian Dold <dold@taler.net>
|
||||
#}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<div>
|
||||
<a href="{{ url('logout') }}" class="pure-button">[{{ _("Logout") }}]</a><br>
|
||||
</div>
|
||||
|
||||
<section id="main">
|
||||
|
||||
{% if hint != "" %}
|
||||
<article>
|
||||
<div class="notification">
|
||||
{% if not is_success %}
|
||||
<p class="informational informational-fail">
|
||||
{% else %}
|
||||
<p class="informational informational-ok">
|
||||
{% endif %}
|
||||
{{ hint }}
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
{% endif %}
|
||||
|
||||
<article>
|
||||
<div>
|
||||
<h2>{{ _("Wire transfer") }}</h2>
|
||||
<p>{{ _("Transfer money via the payto system:") }}
|
||||
<br>
|
||||
<br>
|
||||
<tt style="font-size: 15px">payto://x-taler-bank/[bank-hostname]/[receiver-username]?message=[subject]&amount=[{{ currency }}:X.Y]</tt>
|
||||
</p>
|
||||
<form action="{{ url('payto-transfer') }}"
|
||||
method="POST"
|
||||
name="payto-form">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}" />
|
||||
<input name="address"
|
||||
size="90"
|
||||
placeholder={{ _("payto address") }}
|
||||
pattern="payto://x-taler-bank/[a-z\.]+(:[0-9]+)?/[0-9a-zA-Z]+\?message=[a-zA-Z0-9 ]+&amount={{ currency }}:[0-9]+(\.[0-9]+)?" />
|
||||
<input class="pure-button pure-button-primary"
|
||||
type="submit"
|
||||
value={{ _("Confirm") }} />
|
||||
</form>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -0,0 +1,120 @@
|
|||
{% extends "base.html" %}
|
||||
{#
|
||||
This file is part of GNU TALER.
|
||||
Copyright (C) 2014, 2015, 2016 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Lesser General Public License as published by the Free Software
|
||||
Foundation; either version 2.1, or (at your option) any later version.
|
||||
|
||||
TALER 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
@author Marcello Stanisci
|
||||
@author Florian Dold <dold@taler.net>
|
||||
#}
|
||||
|
||||
{% block main %}
|
||||
<div>
|
||||
<h1 class="nav">
|
||||
{% autoescape off %}
|
||||
{{ _("Welcome <em>{name}</em>!").format(name=name) }}
|
||||
{% endautoescape %}
|
||||
</h1>
|
||||
<a href="{{ url('logout') }}" class="pure-button logout-button">[{{ _("Logout") }}]</a><br>
|
||||
</div>
|
||||
|
||||
<section id="menu">
|
||||
<p>{{ _("Bank account balance") }}: <br/> <b>{{ amount_stringify(balance) }}</b></p>
|
||||
</section>
|
||||
<section id="main">
|
||||
{% if hint != "" %}
|
||||
<article>
|
||||
<div class="notification">
|
||||
{% if not is_success %}
|
||||
<p class="informational informational-fail">
|
||||
{% else %}
|
||||
<p class="informational informational-ok">
|
||||
{% endif %}
|
||||
{{ hint }}
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
{% endif %}
|
||||
<article>
|
||||
<div>
|
||||
<h2>{{ _("Withdraw Money into a Taler wallet") }}</h2>
|
||||
<form id="reserve-form"
|
||||
class="pure-form"
|
||||
action="{{ url('start-withdrawal') }}"
|
||||
method="post"
|
||||
name="tform">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}" />
|
||||
{{ _("Amount to withdraw") }}:
|
||||
{% if settings_value("SHOW_FREEFORM_WITHDRAWAL") %}
|
||||
<input type="number" name="withdraw-amount" class="amount" />
|
||||
{%- else -%}
|
||||
<select id="reserve-amount" name="withdraw-amount" class="amount" autofocus>
|
||||
<option value="5.00">5.00</option>
|
||||
<option value="10.00">10.00</option>
|
||||
<option value="15.00">15.00</option>
|
||||
<option value="20.00">20.00</option>
|
||||
</select>
|
||||
{%- endif -%}
|
||||
<input type="text" readonly class="currency-indicator" size="{{ currency|length }}" tabindex="-1" value="{{ currency }}">
|
||||
<input id="select-exchange"
|
||||
class="pure-button pure-button-primary"
|
||||
type="submit"
|
||||
value="{{ _('Start withdrawal') }}" />
|
||||
</form>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<h2>{{ _("Transactions for") }} {{ name }}</h2>
|
||||
<p><a href={{ url('wiretransfer-form') }}>{{_("Transfer money manually") }}</a></p>
|
||||
<div id="transactions-history">
|
||||
{% if history %}
|
||||
<table class="pure-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:center">{{ _("Date") }}</th>
|
||||
<th style="text-align:center">{{ _("Amount") }}</th>
|
||||
<th style="text-align:center">{{ _("Counterpart") }}</th>
|
||||
<th style="text-align:center">{{ _("Subject") }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in history %}
|
||||
<tr>
|
||||
<td style="text-align:right">{{ item.date }}</td>
|
||||
<td style="text-align:right">
|
||||
{{ item.sign }} {{ item.amount }}
|
||||
</td>
|
||||
<td class="text-align:left">
|
||||
{% if item.counterpart_username %}
|
||||
{{ item.counterpart_username }}
|
||||
{% endif %} (account #{{ item.counterpart }})
|
||||
</td>
|
||||
<td class="text-align:left
|
||||
{% if item.cancelled %}
|
||||
{{ _("cancelled") }}
|
||||
{% endif %}">{{ item.subject }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="informational informational-fail">
|
||||
{{ _("No transactions made to/from this account") }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</article>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -0,0 +1,105 @@
|
|||
{% extends "base.html" %}
|
||||
{#
|
||||
This file is part of GNU TALER.
|
||||
Copyright (C) 2014, 2015, 2016 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Lesser General Public License as published by the Free Software
|
||||
Foundation; either version 2.1, or (at your option) any later version.
|
||||
|
||||
TALER 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
@author Marcello Stanisci
|
||||
#}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<h1 class="nav">{{ _("History of public accounts") }}</h1>
|
||||
|
||||
<a href="{{ url('index') }}">Back</a>
|
||||
<section id="main">
|
||||
<article>
|
||||
{% if hint != "" %}
|
||||
<div class="notification">
|
||||
{% if not is_success %}
|
||||
<p class="informational informational-fail">
|
||||
{% else %}
|
||||
<p class="informational informational-ok">
|
||||
{% endif %}
|
||||
{{ hint }}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div name="accountMenu" class="pure-menu pure-menu-horizontal">
|
||||
<ul class="pure-menu-list">
|
||||
{% for account in public_accounts %}
|
||||
{% if account.account_no == selected_account.number %}
|
||||
<li class="pure-menu-item pure-menu-selected">
|
||||
{% else %}
|
||||
<li class="pure-menu-item pure-menu">
|
||||
{% endif %}
|
||||
<a href="{{ url("public-accounts", name=account.user.username) }}" class="pure-menu-link">
|
||||
{{ account.user.username }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="results">
|
||||
{% if selected_account.history %}
|
||||
<table class="pure-table pure-table-striped">
|
||||
<thead>
|
||||
<th>{{ _("Date") }}</th>
|
||||
<th>{{ _("Amount") }}</th>
|
||||
<th>{{ _("Counterpart") }}</th>
|
||||
<th>{{ _("Subject") }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for entry in selected_account.history %}
|
||||
<tr>
|
||||
<td>{{entry.date}}</td>
|
||||
<td>
|
||||
{{ entry.sign }} {{ entry.amount }}
|
||||
</td>
|
||||
<td>{{ _("account") }} #{{ entry.counterpart }}</td>
|
||||
<td {% if entry.cancelled %} class="cancelled" {% endif %}>
|
||||
{{ entry.subject }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="pages-list">
|
||||
{% if back %}
|
||||
<a
|
||||
class="page-number"
|
||||
href="{{ url("public-accounts", name=selected_account.name, page=back) }}">‹...</a>
|
||||
{% endif %}
|
||||
{% for pagej in pages %}
|
||||
<a
|
||||
{% if pagej == current_page%}
|
||||
class="current-page-number"
|
||||
{% else %}
|
||||
class="page-number"
|
||||
{% endif %}
|
||||
href="{{ url("public-accounts", name=selected_account.name, page=pagej) }}">{{ pagej }}</a>
|
||||
{% endfor %}
|
||||
{% if forth %}
|
||||
<a
|
||||
class="page-number"
|
||||
href="{{ url("public-accounts", name=selected_account.name, page=forth) }}">...›</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<p>{{ _("No history for account #{account_number} ({account_name}) yet").format(account_number=selected_account.number, account_name=selected_account.name) }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
{% endblock main %}
|
|
@ -0,0 +1,39 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<h1 class="nav">{{ _("Register to the {currency} bank!").format(currency=settings_value('TALER_CURRENCY')) }}</h1>
|
||||
|
||||
<aside class="sidebar" id="left">
|
||||
</aside>
|
||||
<section id="main">
|
||||
<article>
|
||||
<a href="{{ url('index') }}">{{ _("Back") }}</a>
|
||||
<div class="notification">
|
||||
{% if wrong %}
|
||||
<p class="informational informational-fail">
|
||||
{{ hint }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if not_available %}
|
||||
<p class="informational informational-fail">
|
||||
{{ _("Sorry, this username is no longer available. Please choose another one!") }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
<section id="main">
|
||||
<article>
|
||||
<div class="register-form">
|
||||
<h1>{{ _("Registration form") }}</h1>
|
||||
<form class="pure-form" method="post" action="{{ url('register') }}">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}" />
|
||||
<input type="text" name="username" placeholder="username" autofocus />
|
||||
<input type="password" name="password" placeholder="password" />
|
||||
<input type="submit" value="{{ _('Sign Up') }}" class="pure-button pure-button-primary" />
|
||||
</form>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
{% endblock main %}
|
|
@ -0,0 +1,72 @@
|
|||
{% extends "base.html" %}
|
||||
{#
|
||||
This file is part of GNU TALER.
|
||||
Copyright (C) 2014, 2015, 2016 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Lesser General Public License as published by the Free Software
|
||||
Foundation; either version 2.1, or (at your option) any later version.
|
||||
|
||||
TALER 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
@author Marcello Stanisci
|
||||
@author Florian Dold <dold@taler.net>
|
||||
#}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<div>
|
||||
<a href="{{ url('logout') }}" class="pure-button">[{{ _("Logout") }}]</a><br>
|
||||
</div>
|
||||
|
||||
<section id="main">
|
||||
|
||||
{% if hint != "" %}
|
||||
<article>
|
||||
<div class="notification">
|
||||
{% if not is_success %}
|
||||
<p class="informational informational-fail">
|
||||
{% else %}
|
||||
<p class="informational informational-ok">
|
||||
{% endif %}
|
||||
{{ hint }}
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
{% endif %}
|
||||
|
||||
<article>
|
||||
<div>
|
||||
<h2>{{ _("Wire transfer") }}</h2>
|
||||
<p>{{ _("Transfer money to another account of this bank:") }}
|
||||
<br>
|
||||
<br>
|
||||
</p>
|
||||
<form action="{{ url('wiretransfer-form') }}"
|
||||
method="POST"
|
||||
name="wire-transfer-form">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}" />
|
||||
<input name="receiver" placeholder={{ _("receiver") }} required />
|
||||
<br>
|
||||
<br>
|
||||
<input name="subject" placeholder={{ _("subject") }} required />
|
||||
<br>
|
||||
<br>
|
||||
<input name="amount" placeholder="XY.XY" pattern="[0-9]+(\.[0-9]+)?" required>
|
||||
<label>{{ currency }}</label>
|
||||
</input>
|
||||
<input type="hidden" name="currency" value={{ currency }} />
|
||||
<br>
|
||||
<br>
|
||||
<input class="pure-button pure-button-primary" type="submit" value={{ _("Confirm") }} />
|
||||
</form>
|
||||
<p><a href="{{ url('payto-form') }}">Want to try the raw payto://-format?</a></p>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -0,0 +1,47 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<h1 class="nav">{{ _("Confirm Withdrawal") }}</h1>
|
||||
|
||||
{% if not is_success %}
|
||||
<p class="informational informational-fail">
|
||||
{{ hint }}
|
||||
</p>
|
||||
{% endif %}
|
||||
<p>
|
||||
{% autoescape off %}
|
||||
{{ _("{currency} Bank needs to verify that you intend to withdraw <b>{amount}</b> from <b>{exchange}</b>. To prove that you are the account owner, please answer the following "security question" (*):").format(currency=settings_value("TALER_CURRENCY"), amount=amount, exchange=exchange) }}
|
||||
{% endautoescape %}
|
||||
</p>
|
||||
<p>
|
||||
{{ _("What is {question}?").format(question=question) }}
|
||||
</p>
|
||||
<div>
|
||||
<form
|
||||
method="post"
|
||||
action="{{ url('withdraw-confirm', withdraw_id) }}"
|
||||
class="pure-form"
|
||||
style="float: left;">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}" />
|
||||
<input type="text" name="pin_0" value="" autocomplete="off" autofocus />
|
||||
<input type="hidden" name="pin_1" value="{{ hashed_answer }}" />
|
||||
<input type="hidden" name="question_url" value="{{ request.get_full_path() }}" />
|
||||
<input type="submit" value="Ok" class="pure-button pure-button-primary" />
|
||||
</form>
|
||||
<form
|
||||
method="post"
|
||||
action="{{ url('abort-withdrawal', withdraw_id=withdraw_id) }}"
|
||||
class="pure-form">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}" />
|
||||
<input
|
||||
type="submit"
|
||||
value="Abort"
|
||||
class="pure-button pure-button-primary abort-button" />
|
||||
</form>
|
||||
</div>
|
||||
<p>
|
||||
<small style="margin: 40px 0px">(*) {{ _("A real bank should ask for a PIN/TAN instead of a simple calculation. For example by sending a one time password to the customer's mobile or providing her a random password generator.") }}
|
||||
<small>
|
||||
</p>
|
||||
{% endblock main %}
|
|
@ -0,0 +1,50 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block head %}
|
||||
<script>
|
||||
// prettier-ignore
|
||||
let checkUrl = JSON.parse('{{ withdraw_check_url | tojson }}');
|
||||
let delayMs = 500;
|
||||
function check() {
|
||||
let req = new XMLHttpRequest();
|
||||
req.onreadystatechange = function () {
|
||||
if (req.readyState === XMLHttpRequest.DONE) {
|
||||
if (req.status === 200) {
|
||||
try {
|
||||
let resp = JSON.parse(req.responseText);
|
||||
if (resp.selection_done) {
|
||||
document.location.reload(true);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("could not parse response:", e);
|
||||
}
|
||||
}
|
||||
setTimeout(check, delayMs);
|
||||
}
|
||||
};
|
||||
req.onerror = function () {
|
||||
setTimeout(check, delayMs);
|
||||
}
|
||||
req.open("GET", checkUrl);
|
||||
req.send();
|
||||
}
|
||||
|
||||
setTimeout(check, delayMs);
|
||||
|
||||
</script>
|
||||
{% endblock head %}
|
||||
|
||||
{% block main %}
|
||||
<h1 class="nav">{{ _("Withdraw to a Taler Wallet") }}</h1>
|
||||
|
||||
<p>
|
||||
{{ _("You can use this QR code to withdraw to your mobile wallet:") }}
|
||||
</p>
|
||||
{{ qrcode_svg | safe }}
|
||||
<p>
|
||||
{% autoescape off %}
|
||||
{{ _("Click <a href=\"{taler_withdraw_uri}\">this link</a> to open your system's Taler wallet if it exists.").format(taler_withdraw_uri=taler_withdraw_uri) }}
|
||||
{% endautoescape %}
|
||||
</p>
|
||||
|
||||
{% endblock main %}
|
|
@ -0,0 +1,17 @@
|
|||
# Config file containing intentional errors, used
|
||||
# to test how the bank reacts.
|
||||
|
||||
[taler]
|
||||
|
||||
CURRENCY = KUDOS
|
||||
|
||||
[bank]
|
||||
|
||||
# Which database should we use?
|
||||
DATABASE = postgres:///talercheck
|
||||
|
||||
# FIXME
|
||||
MAX_DEBT = 33 KUDOS
|
||||
|
||||
# FIXME
|
||||
MAX_DEBT_BANK = KUDOS:0
|
|
@ -0,0 +1,10 @@
|
|||
[bank]
|
||||
|
||||
# Which database should we use?
|
||||
DATABASE = postgres:///talerbank
|
||||
|
||||
# FIXME
|
||||
MAX_DEBT = KUDOS:50
|
||||
|
||||
# FIXME
|
||||
MAX_DEBT_BANK = KUDOS:0
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
[taler]
|
||||
|
||||
CURRENCY = KUDOS
|
||||
|
||||
[bank]
|
||||
|
||||
ALLOW_REGISTRATIONS = yes
|
||||
|
||||
# Which database should we use?
|
||||
DATABASE = postgres:///talercheck
|
||||
NDIGITS = 2
|
||||
|
||||
# FIXME
|
||||
MAX_DEBT = KUDOS:50.0
|
||||
|
||||
# FIXME
|
||||
MAX_DEBT_BANK = KUDOS:1000000
|
||||
|
||||
UWSGI_SERVE = unix
|
||||
UWSGI_UNIXPATH = /tmp/banktest-unused.uwsgi
|
||||
UWSGI_UNIXPATH_MODE = 660
|
||||
SUGGESTED_EXCHANGE_PAYTO = payto://x-taler-bank/bank.example.com/2
|
|
@ -0,0 +1,798 @@
|
|||
# This file is part of TALER
|
||||
# (C) 2014, 2015, 2016 Taler Systems SA
|
||||
#
|
||||
# TALER 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,
|
||||
# or (at your option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not,
|
||||
# see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# @author Marcello Stanisci
|
||||
|
||||
import json
|
||||
import time
|
||||
import uuid
|
||||
import zlib
|
||||
import timeit
|
||||
import logging
|
||||
import unittest
|
||||
import base64
|
||||
from urllib.parse import unquote
|
||||
from django.db import connection
|
||||
from django.test import TestCase, Client
|
||||
from django.urls import reverse
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from mock import patch, MagicMock
|
||||
from .models import BankAccount, BankTransaction, TalerWithdrawOperation
|
||||
from . import urls
|
||||
from .views import wire_transfer, get_reserve_pub
|
||||
from taler.util.payto import PaytoParse, PaytoFormatError
|
||||
from taler.util.amount import (
|
||||
Amount,
|
||||
SignedAmount,
|
||||
CurrencyMismatchError,
|
||||
AmountFormatError,
|
||||
)
|
||||
|
||||
LOGGER = logging.getLogger()
|
||||
LOGGER.setLevel(logging.DEBUG)
|
||||
LOGGER.handlers = []
|
||||
# Logfile opens in 'append' mode.
|
||||
fileHandler = logging.FileHandler("tests.log")
|
||||
fileHandler.setLevel(logging.DEBUG)
|
||||
fileHandler.setFormatter(
|
||||
logging.Formatter(fmt="%(asctime)-15s %(module)s %(levelname)s %(message)s")
|
||||
)
|
||||
LOGGER.addHandler(fileHandler)
|
||||
|
||||
|
||||
def make_auth_line(username, password):
|
||||
credentials = "%s:%s" % (username, password)
|
||||
b64enc = base64.b64encode(bytes(credentials, "utf-8"))
|
||||
header_line = "Basic %s" % b64enc.decode()
|
||||
return header_line
|
||||
|
||||
|
||||
def clear_db():
|
||||
User.objects.all().delete()
|
||||
BankAccount.objects.all().delete()
|
||||
BankTransaction.objects.all().delete()
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("ALTER SEQUENCE app_bankaccount_account_no_seq" " RESTART")
|
||||
cursor.execute("ALTER SEQUENCE app_banktransaction_id_seq RESTART")
|
||||
|
||||
|
||||
class WireGatewayTestCase(TestCase):
|
||||
def setUp(self):
|
||||
clear_db()
|
||||
exchange = User.objects.create_user(username="RandomExchange", password="XYZ")
|
||||
exchange.save()
|
||||
customer = User.objects.create_user(username="RandomCustomer", password="ABC")
|
||||
customer.save()
|
||||
exchange_bank_account = BankAccount(
|
||||
user=exchange,
|
||||
balance=SignedAmount(True, Amount(settings.TALER_CURRENCY, 100, 0)),
|
||||
)
|
||||
exchange_bank_account.save()
|
||||
customer_bank_account = BankAccount(
|
||||
user=customer,
|
||||
balance=SignedAmount(True, Amount(settings.TALER_CURRENCY, 100, 0)),
|
||||
)
|
||||
customer_bank_account.save()
|
||||
self.client = Client()
|
||||
|
||||
def test_all(self):
|
||||
r = self.client.post(
|
||||
reverse("twg-add-incoming", kwargs=dict(acct_id="RandomExchange")),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomExchange", "XYZ"),
|
||||
content_type="application/json",
|
||||
data=dict(
|
||||
amount=f"{settings.TALER_CURRENCY}:10",
|
||||
reserve_pub="FXWC2JHBY8B0XE2MMGAJ9TGPY307TN12HVEKYSTN6HE3GTHTF8XG",
|
||||
debit_account="payto://x-taler-bank/localhost/RandomCustomer",
|
||||
),
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
# Test incoming transfers of Exchange.
|
||||
r = self.client.get(
|
||||
reverse("twg-history-incoming", kwargs=dict(acct_id="RandomExchange")),
|
||||
dict(delta=5),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomExchange", "XYZ"),
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
# Test outgoing transfers of the Exchange.
|
||||
r = self.client.post(
|
||||
reverse("twg-transfer", kwargs=dict(acct_id="RandomExchange")),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomExchange", "XYZ"),
|
||||
content_type="application/json",
|
||||
data=dict(
|
||||
request_uid="0",
|
||||
amount=f"{settings.TALER_CURRENCY}:3",
|
||||
exchange_base_url="mock",
|
||||
wtid="123",
|
||||
credit_account="payto://x-taler-bank/localhost/RandomCustomer",
|
||||
),
|
||||
)
|
||||
r = self.client.get(
|
||||
reverse("twg-history-outgoing", kwargs=dict(acct_id="RandomExchange")),
|
||||
dict(delta=5),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomExchange", "XYZ"),
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
|
||||
class IntegrationApiTestCase(TestCase):
|
||||
def setUp(self):
|
||||
clear_db()
|
||||
|
||||
self.exchange = User.objects.create_user(
|
||||
username="RandomExchange", password="XYZ"
|
||||
)
|
||||
self.exchange.save()
|
||||
self.exchange_bank_account = BankAccount(
|
||||
user=self.exchange,
|
||||
balance=SignedAmount(True, Amount(settings.TALER_CURRENCY, 100, 0)),
|
||||
)
|
||||
self.exchange_bank_account.save()
|
||||
|
||||
self.user = User.objects.create_user(username="RandomUser", password="XYZ")
|
||||
self.user.save()
|
||||
self.user_bank_account = BankAccount(
|
||||
user=self.user,
|
||||
balance=SignedAmount(True, Amount(settings.TALER_CURRENCY, 100, 0)),
|
||||
)
|
||||
self.user_bank_account.save()
|
||||
self.client = Client()
|
||||
|
||||
def test_config(self):
|
||||
c = Client()
|
||||
r = c.get("/config")
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
def test_withdraw(self):
|
||||
operation = TalerWithdrawOperation(
|
||||
amount=Amount(settings.TALER_CURRENCY, 100, 0),
|
||||
withdraw_account=self.user_bank_account,
|
||||
)
|
||||
operation.save()
|
||||
r = self.client.post(
|
||||
reverse(
|
||||
"api-withdraw-operation", kwargs=dict(withdraw_id=operation.withdraw_id)
|
||||
),
|
||||
data=dict(
|
||||
reserve_pub="reserve-public-key",
|
||||
selected_exchange=f"payto://x-taler-bank/localhost/RandomExchange",
|
||||
),
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
|
||||
class AccessApiWithdrawTestCase(TestCase):
|
||||
def setUp(self):
|
||||
clear_db()
|
||||
self.user = User.objects.create_user(username="RandomUser", password="XYZ")
|
||||
self.user.save()
|
||||
self.user_bank_account = BankAccount(
|
||||
user=self.user,
|
||||
balance=SignedAmount(True, Amount(settings.TALER_CURRENCY, 100, 0)),
|
||||
)
|
||||
self.user_bank_account.save()
|
||||
self.client = Client()
|
||||
|
||||
def create_withdrawal(self):
|
||||
r = self.client.post(
|
||||
reverse("access-api-withdrawal", kwargs=dict(acct_id="RandomUser")),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomUser", "XYZ"),
|
||||
content_type="application/json",
|
||||
data=dict(amount=f"{settings.TALER_CURRENCY}:5"),
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
data = r.content.decode("utf-8")
|
||||
data_dict = json.loads(data)
|
||||
withdrawal_id = data_dict.get("withdrawal_id")
|
||||
self.assertTrue(withdrawal_id)
|
||||
return withdrawal_id
|
||||
|
||||
def test_accees_withdraw_create(self):
|
||||
self.create_withdrawal()
|
||||
|
||||
def test_accees_withdraw_status(self):
|
||||
withdrawal_id = self.create_withdrawal()
|
||||
r = self.client.get(
|
||||
reverse(
|
||||
"access-api-withdrawal-status",
|
||||
kwargs=dict(acct_id="RandomUser", wid=withdrawal_id),
|
||||
),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomUser", "XYZ"),
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
def test_accees_withdraw_abort(self):
|
||||
withdrawal_id = self.create_withdrawal()
|
||||
r = self.client.post(
|
||||
reverse(
|
||||
"access-api-withdrawal-abort",
|
||||
kwargs=dict(acct_id="RandomUser", wid=withdrawal_id),
|
||||
),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomUser", "XYZ"),
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
def test_accees_withdraw_confirm(self):
|
||||
withdrawal_id = self.create_withdrawal()
|
||||
r = self.client.post(
|
||||
reverse(
|
||||
"access-api-withdrawal-confirm",
|
||||
kwargs=dict(acct_id="RandomUser", wid=withdrawal_id),
|
||||
),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomUser", "XYZ"),
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
def test_accees_withdraw_abort_then_confirm(self):
|
||||
withdrawal_id = self.create_withdrawal()
|
||||
r = self.client.post(
|
||||
reverse(
|
||||
"access-api-withdrawal-abort",
|
||||
kwargs=dict(acct_id="RandomUser", wid=withdrawal_id),
|
||||
),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomUser", "XYZ"),
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
r = self.client.post(
|
||||
reverse(
|
||||
"access-api-withdrawal-confirm",
|
||||
kwargs=dict(acct_id="RandomUser", wid=withdrawal_id),
|
||||
),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomUser", "XYZ"),
|
||||
)
|
||||
self.assertEqual(r.status_code, 409)
|
||||
|
||||
def test_integration_api_withdraw_status(self):
|
||||
wid = self.create_withdrawal()
|
||||
r = self.client.get(
|
||||
reverse(
|
||||
"access-api-withdrawal-status",
|
||||
kwargs=dict(acct_id="RandomUser", wid=wid),
|
||||
),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomUser", "XYZ"),
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
def test_integration_api_withdraw_confirm(self):
|
||||
wid = self.create_withdrawal()
|
||||
r = self.client.post(
|
||||
reverse(
|
||||
"access-api-withdrawal-confirm",
|
||||
kwargs=dict(acct_id="RandomUser", wid=wid),
|
||||
),
|
||||
data=dict(
|
||||
reserve_pub="FXWC2JHBY8B0XE2MMGAJ9TGPY307TN12HVEKYSTN6HE3GTHTF8XG",
|
||||
selected_exchange="payto://x-taler-bank/localhost/RandomUser",
|
||||
),
|
||||
content_type="application/json",
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomUser", "XYZ"),
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
|
||||
class AccessApiBalanceTestCase(TestCase):
|
||||
def setUp(self):
|
||||
clear_db()
|
||||
self.user = User.objects.create_user(username="RandomUser", password="XYZ")
|
||||
self.user.save()
|
||||
self.user_bank_account = BankAccount(user=self.user)
|
||||
self.user_bank_account.save()
|
||||
|
||||
def test_balance(self):
|
||||
c = Client()
|
||||
r = c.get(
|
||||
reverse("access-api-balance", kwargs=dict(acct_id="RandomUser")),
|
||||
HTTP_AUTHORIZATION=make_auth_line("RandomUser", "XYZ"),
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
|
||||
class AccessApiTestingRegistrationTestCase(TestCase):
|
||||
def setUp(self):
|
||||
clear_db()
|
||||
self.user = User.objects.create_user(username="Bank", password="Bank")
|
||||
self.user.save()
|
||||
self.user_bank_account = BankAccount(user=self.user)
|
||||
self.user_bank_account.save()
|
||||
|
||||
def test_testing_registration(self):
|
||||
c = Client()
|
||||
r = c.post(
|
||||
reverse("testing-withdraw-register"),
|
||||
data=dict(username="x", password="y"),
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
|
||||
class ReservePubExtractionTestCase(TestCase):
|
||||
def test_extraction(self):
|
||||
self.assertTrue(
|
||||
get_reserve_pub("0T096A11M57GWGG0P6ZM9Z8G5829BFJFH2AN9R5T80FJ931DX7GG")
|
||||
)
|
||||
self.assertTrue(
|
||||
get_reserve_pub(
|
||||
"0T096A11M57GWGG0P6ZM9Z8G5829BFJFH2AN9R5T80FJ931DX7GG other data"
|
||||
)
|
||||
)
|
||||
self.assertFalse(get_reserve_pub("not a reserve public key"))
|
||||
|
||||
|
||||
class PaytoParseTestCase(TestCase):
|
||||
def test_payto_wrong_protocol(self):
|
||||
self.assertRaises(PaytoFormatError, PaytoParse, "http://foo/bar")
|
||||
def test_payto_with_port_number(self):
|
||||
parsed = PaytoParse("payto://iban/localhost:1234/account")
|
||||
self.assertEqual(parsed.bank, "localhost:1234")
|
||||
def test_minimal(self):
|
||||
parsed = PaytoParse("payto://x-taler-bank/bank-hostname/Taler")
|
||||
def test_payto_malformed(self):
|
||||
self.assertRaises(PaytoFormatError, PaytoParse, "payto:foo/bar")
|
||||
def test_payto_noamount(self):
|
||||
parsed = PaytoParse(
|
||||
"payto://x-taler-bank/bank.int.taler.net/Exchange?message=0T096A11M57GWGG0P6ZM9Z8G5829BFJFH2AN9R5T80FJ931DX7GG"
|
||||
)
|
||||
def test_payto_parse(self):
|
||||
parsed = PaytoParse(
|
||||
"payto://x-taler-bank/bank.int.taler.net/Exchange?message=0T096A11M57GWGG0P6ZM9Z8G5829BFJFH2AN9R5T80FJ931DX7GG&amount=EUR:1"
|
||||
)
|
||||
self.assertEqual("Exchange", parsed.target)
|
||||
self.assertEqual("0T096A11M57GWGG0P6ZM9Z8G5829BFJFH2AN9R5T80FJ931DX7GG", parsed.message)
|
||||
self.assertEqual(parsed.amount.value, 1)
|
||||
self.assertEqual(parsed.amount.fraction, 0)
|
||||
self.assertEqual(parsed.amount.currency, "EUR")
|
||||
self.assertEqual(parsed.authority, "x-taler-bank")
|
||||
self.assertEqual(parsed.bank, "bank.int.taler.net")
|
||||
|
||||
|
||||
class PublicAccountsTestCase(TestCase):
|
||||
def setUp(self):
|
||||
clear_db()
|
||||
self.user = User.objects.create_user(username="Bank", password="Bank")
|
||||
self.user.save()
|
||||
|
||||
self.user_bank_account = BankAccount(
|
||||
account_no=100, is_public=True, user=self.user
|
||||
)
|
||||
|
||||
self.user_bank_account.save()
|
||||
|
||||
def test_public_accounts(self):
|
||||
self.assertTrue(User.objects.get(username="Bank"))
|
||||
|
||||
response = self.client.get(reverse("public-accounts", urlconf=urls))
|
||||
|
||||
|
||||
class WithdrawTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.user_bank_account = BankAccount(
|
||||
user=User.objects.create_user(
|
||||
username="test_user", password="test_password"
|
||||
),
|
||||
account_no=100,
|
||||
)
|
||||
self.user_bank_account.save()
|
||||
|
||||
self.exchange_bank_account = BankAccount(
|
||||
user=User.objects.create_user(username="test_exchange", password=""),
|
||||
account_no=99,
|
||||
)
|
||||
self.exchange_bank_account.save()
|
||||
self.client = Client()
|
||||
|
||||
@patch("talerbank.app.views.wire_transfer")
|
||||
@patch("hashlib.new")
|
||||
@patch("time.time")
|
||||
@unittest.skip("skip outdated test case")
|
||||
def test_withdraw(self, mocked_time, mocked_hashlib, mocked_wire_transfer):
|
||||
amount = Amount(settings.TALER_CURRENCY, 0, 1)
|
||||
params = {
|
||||
"amount_value": str(amount.value),
|
||||
"amount_fraction": str(amount.fraction),
|
||||
"amount_currency": amount.currency,
|
||||
"reserve_pub": "UVZ789",
|
||||
"exchange": "https://exchange.example.com/",
|
||||
"exchange_wire_details": "payto://x-taler-bank/bank.example/99",
|
||||
}
|
||||
self.client.login(username="test_user", password="test_password")
|
||||
|
||||
response = self.client.get(reverse("pin-question", urlconf=urls), params)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# We mock hashlib in order to fake the CAPTCHA.
|
||||
hasher = MagicMock()
|
||||
hasher.hexdigest = MagicMock()
|
||||
hasher.hexdigest.return_value = "0"
|
||||
mocked_hashlib.return_value = hasher
|
||||
mocked_time.return_value = 0
|
||||
|
||||
response = self.client.post(
|
||||
reverse("withdraw-confirm", urlconf=urls), {"pin_1": "0"}
|
||||
)
|
||||
|
||||
args, kwargs = mocked_wire_transfer.call_args
|
||||
del kwargs
|
||||
self.assertTrue(
|
||||
args[0].dump() == amount.dump()
|
||||
and self.user_bank_account in args
|
||||
and "UVZ789" in args
|
||||
and self.exchange_bank_account in args
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
clear_db()
|
||||
|
||||
|
||||
class RegisterTestCase(TestCase):
|
||||
"""User registration"""
|
||||
|
||||
def setUp(self):
|
||||
clear_db()
|
||||
BankAccount(user=User.objects.create_user(username="Bank")).save()
|
||||
|
||||
def tearDown(self):
|
||||
clear_db()
|
||||
|
||||
def test_register(self):
|
||||
setattr(settings, "ALLOW_REGISTRATIONS", True)
|
||||
client = Client()
|
||||
response = client.post(
|
||||
reverse("register", urlconf=urls),
|
||||
{"username": "test_register", "password": "test_register"},
|
||||
follow=True,
|
||||
)
|
||||
self.assertIn(("/en/profile", 302), response.redirect_chain)
|
||||
# this assertion tests "/profile""s view
|
||||
self.assertEqual(200, response.status_code)
|
||||
|
||||
def test_register_headless(self):
|
||||
setattr(settings, "ALLOW_REGISTRATIONS", True)
|
||||
client = Client()
|
||||
|
||||
# Normal case.
|
||||
response = client.post(
|
||||
reverse("testing-withdraw-register", urlconf=urls),
|
||||
content_type="application/json",
|
||||
data={"username": "test_register_headless", "password": "password*+#@"},
|
||||
)
|
||||
self.assertEqual(200, response.status_code)
|
||||
|
||||
# Double-check account creation.
|
||||
self.assertTrue(
|
||||
self.client.login(
|
||||
username="test_register_headless", password="password*+#@"
|
||||
)
|
||||
)
|
||||
|
||||
# Try registering unavailable username.
|
||||
response = client.post(
|
||||
reverse("testing-withdraw-register", urlconf=urls),
|
||||
content_type="application/json",
|
||||
data={"username": "test_register_headless", "password": "password"},
|
||||
)
|
||||
self.assertEqual(409, response.status_code)
|
||||
|
||||
# NOTE: Django 2.2.2 allows ANY character! Is this normal?
|
||||
response = client.post(
|
||||
reverse("testing-withdraw-register", urlconf=urls),
|
||||
content_type="application/json",
|
||||
data={"username": "'''+++;;;'''", "password": "password2"},
|
||||
)
|
||||
self.assertEqual(200, response.status_code)
|
||||
|
||||
|
||||
class LoginTestCase(TestCase):
|
||||
"""User login"""
|
||||
|
||||
def setUp(self):
|
||||
BankAccount(
|
||||
user=User.objects.create_user(
|
||||
username="test_user", password="test_password"
|
||||
)
|
||||
).save()
|
||||
self.client = Client()
|
||||
|
||||
def tearDown(self):
|
||||
clear_db()
|
||||
|
||||
def test_login(self):
|
||||
self.assertTrue(
|
||||
self.client.login(username="test_user", password="test_password")
|
||||
)
|
||||
self.assertFalse(
|
||||
self.client.login(username="test_user", password="test_passwordii")
|
||||
)
|
||||
|
||||
def test_failing_login(self):
|
||||
response = self.client.get(
|
||||
reverse("history", urlconf=urls),
|
||||
{"auth": "basic"},
|
||||
HTTP_AUTHORIZATION=make_auth_line("Wrong", "Credentials"),
|
||||
)
|
||||
data = response.content.decode("utf-8")
|
||||
self.assertEqual(401, response.status_code)
|
||||
|
||||
|
||||
class AddIncomingTestCase(TestCase):
|
||||
"""Test money transfer's API"""
|
||||
|
||||
def setUp(self):
|
||||
BankAccount(
|
||||
user=User.objects.create_user(
|
||||
username="bank_user", password="bank_password"
|
||||
)
|
||||
).save()
|
||||
BankAccount(
|
||||
user=User.objects.create_user(
|
||||
username="user_user", password="user_password"
|
||||
)
|
||||
).save()
|
||||
|
||||
def tearDown(self):
|
||||
clear_db()
|
||||
|
||||
def test_add_incoming(self):
|
||||
client = Client()
|
||||
request_body = dict(
|
||||
reserve_pub="TESTWTID",
|
||||
amount=f"{settings.TALER_CURRENCY}:1.0",
|
||||
debit_account="payto://x-taler-bank/bank_user",
|
||||
)
|
||||
response = client.post(
|
||||
reverse("twg-add-incoming", urlconf=urls, args=["user_user"]),
|
||||
data=json.dumps(request_body),
|
||||
content_type="application/json",
|
||||
follow=True,
|
||||
HTTP_AUTHORIZATION=make_auth_line("user_user", "user_password"),
|
||||
)
|
||||
self.assertEqual(200, response.status_code)
|
||||
|
||||
|
||||
class CustomDoesNotExistTestCase(TestCase):
|
||||
def test_bankaccount_doesnotexist(self):
|
||||
with self.assertRaises(BankAccount.DoesNotExist):
|
||||
BankAccount.objects.get(account_no=1000)
|
||||
with self.assertRaises(BankTransaction.DoesNotExist):
|
||||
BankTransaction.objects.get(subject="1000")
|
||||
|
||||
|
||||
class HistoryTestCase(TestCase):
|
||||
def setUp(self):
|
||||
clear_db()
|
||||
debit_account = BankAccount(
|
||||
user=User.objects.create_user(username="User", password="Password"),
|
||||
balance=SignedAmount(True, Amount(settings.TALER_CURRENCY, 100, 0)),
|
||||
)
|
||||
debit_account.save()
|
||||
credit_account = BankAccount(
|
||||
user=User.objects.create_user(username="User0", password="Password0")
|
||||
)
|
||||
credit_account.save()
|
||||
for subject in ("a", "b", "c", "d", "e", "f", "g", "h", "i"):
|
||||
wire_transfer(
|
||||
Amount(settings.TALER_CURRENCY, 1, 0),
|
||||
debit_account,
|
||||
credit_account,
|
||||
subject,
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
clear_db()
|
||||
|
||||
def test_history(self):
|
||||
def histquery(**urlargs):
|
||||
response = self.client.get(
|
||||
reverse("history", urlconf=urls),
|
||||
urlargs,
|
||||
HTTP_AUTHORIZATION=make_auth_line("User", "Password"),
|
||||
)
|
||||
return response
|
||||
|
||||
# test query #1
|
||||
r = histquery(delta="-4", direction="both")
|
||||
rd = json.loads(r.content)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
# test query #2
|
||||
r = histquery(delta="+1", start="5", direction="both")
|
||||
self.assertEqual(r.status_code, 200)
|
||||
rd = json.loads(r.content)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertEqual(rd["data"][0]["row_id"], 6)
|
||||
|
||||
# test query #3
|
||||
r = histquery(delta="+1", start="2", direction="both")
|
||||
self.assertEqual(r.status_code, 200)
|
||||
rd = json.loads(r.content)
|
||||
self.assertEqual(rd["data"][0]["wt_subject"], "c")
|
||||
|
||||
# test query #4
|
||||
r = histquery(delta="-1", start="2", direction="both")
|
||||
self.assertEqual(r.status_code, 200)
|
||||
rd = json.loads(r.content)
|
||||
self.assertEqual(rd["data"][0]["wt_subject"], "a")
|
||||
|
||||
# test query #5
|
||||
r = histquery(delta="1", start="11", direction="both")
|
||||
self.assertEqual(r.status_code, 200)
|
||||
rd = json.loads(r.content)
|
||||
self.assertEqual(len(rd["data"]), 0)
|
||||
|
||||
|
||||
class DBCustomColumnTestCase(TestCase):
|
||||
def setUp(self):
|
||||
BankAccount(user=User.objects.create_user(username="U")).save()
|
||||
|
||||
def tearDown(self):
|
||||
clear_db()
|
||||
|
||||
def test_exists(self):
|
||||
user_bankaccount = BankAccount.objects.get(user=User.objects.get(username="U"))
|
||||
self.assertTrue(isinstance(user_bankaccount.balance, SignedAmount))
|
||||
|
||||
|
||||
## This tests whether a bank account goes debit and then goes >=0
|
||||
## again
|
||||
class DebitTestCase(TestCase):
|
||||
def setUp(self):
|
||||
BankAccount(user=User.objects.create_user(username="U")).save()
|
||||
BankAccount(user=User.objects.create_user(username="U0")).save()
|
||||
|
||||
def tearDown(self):
|
||||
clear_db()
|
||||
|
||||
def test_green(self):
|
||||
user_bankaccount = BankAccount.objects.get(user=User.objects.get(username="U"))
|
||||
self.assertTrue(user_bankaccount.balance.is_zero())
|
||||
|
||||
def test_red(self):
|
||||
user_bankaccount = BankAccount.objects.get(user=User.objects.get(username="U"))
|
||||
user_bankaccount0 = BankAccount.objects.get(
|
||||
user=User.objects.get(username="U0")
|
||||
)
|
||||
|
||||
wire_transfer(
|
||||
Amount(settings.TALER_CURRENCY, 10, 0),
|
||||
user_bankaccount0,
|
||||
user_bankaccount,
|
||||
"Go green",
|
||||
)
|
||||
|
||||
wire_transfer(
|
||||
Amount(settings.TALER_CURRENCY, 11, 0),
|
||||
user_bankaccount,
|
||||
user_bankaccount0,
|
||||
"Go red",
|
||||
)
|
||||
|
||||
amt_one = SignedAmount.parse(f"{settings.TALER_CURRENCY}:1")
|
||||
|
||||
self.assertEqual(user_bankaccount.balance, -amt_one)
|
||||
self.assertEqual(user_bankaccount0.balance, amt_one)
|
||||
|
||||
|
||||
class MeasureHistory(TestCase):
|
||||
def setUp(self):
|
||||
self.user_bankaccount0 = BankAccount(
|
||||
user=User.objects.create_user(username="U0"),
|
||||
balance=SignedAmount(True, Amount(settings.TALER_CURRENCY, 3000, 0)),
|
||||
)
|
||||
self.user_bankaccount0.save()
|
||||
|
||||
user_bankaccount = BankAccount(user=User.objects.create_user(username="U"))
|
||||
user_bankaccount.save()
|
||||
|
||||
self.ntransfers = 1000
|
||||
|
||||
# Make sure logging level is WARNING, otherwise the loop
|
||||
# will overwhelm the console.
|
||||
for i in range(self.ntransfers):
|
||||
del i # to pacify PEP checkers
|
||||
wire_transfer(
|
||||
Amount(settings.TALER_CURRENCY, 1, 0),
|
||||
self.user_bankaccount0,
|
||||
user_bankaccount,
|
||||
"bulk",
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
clear_db()
|
||||
|
||||
def test_extract_history(self):
|
||||
|
||||
# Measure the time extract_history() needs to retrieve
|
||||
# ~ntransfers records.
|
||||
timer = timeit.Timer(
|
||||
stmt="extract_history(self.user_bankaccount0, False)",
|
||||
setup="from talerbank.app.views import extract_history",
|
||||
globals=locals(),
|
||||
)
|
||||
total_time = timer.timeit(number=1)
|
||||
allowed_time_per_record = 0.003
|
||||
self.assertLess(total_time, self.ntransfers * allowed_time_per_record)
|
||||
|
||||
|
||||
class BalanceTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.the_bank = BankAccount(
|
||||
user=User.objects.create_user(username="U0", password="U0PASS"),
|
||||
balance=SignedAmount(True, Amount(settings.TALER_CURRENCY, 3, 0)),
|
||||
)
|
||||
self.the_bank.save()
|
||||
|
||||
user = BankAccount(
|
||||
user=User.objects.create_user(username="U"),
|
||||
balance=SignedAmount(True, Amount(settings.TALER_CURRENCY, 10, 0)),
|
||||
)
|
||||
user.save()
|
||||
|
||||
# bank: 3, user: 10 (START).
|
||||
|
||||
# bank: 2, user: 11
|
||||
wire_transfer(
|
||||
Amount(settings.TALER_CURRENCY, 1, 0), self.the_bank, user, "mock"
|
||||
)
|
||||
|
||||
# bank: 4, user: 9
|
||||
wire_transfer(
|
||||
Amount(settings.TALER_CURRENCY, 2, 0), user, self.the_bank, "mock"
|
||||
)
|
||||
|
||||
# bank: -1, user: 14
|
||||
wire_transfer(
|
||||
Amount(settings.TALER_CURRENCY, 5, 0), self.the_bank, user, "mock"
|
||||
)
|
||||
|
||||
# bank: 7, user: 6 (END)
|
||||
wire_transfer(
|
||||
Amount(settings.TALER_CURRENCY, 8, 0), user, self.the_bank, "mock"
|
||||
)
|
||||
|
||||
# bank: -3, user: 16 (END)
|
||||
wire_transfer(
|
||||
Amount(settings.TALER_CURRENCY, 10, 0), self.the_bank, user, "mock"
|
||||
)
|
||||
|
||||
self.client = Client()
|
||||
|
||||
def tearDown(self):
|
||||
clear_db()
|
||||
|
||||
def test_balance(self):
|
||||
self.client.login(username="U0", password="U0PASS")
|
||||
response = self.client.get(
|
||||
reverse("history", urlconf=urls),
|
||||
{"delta": -30, "direction": "both", "account_number": 55},
|
||||
HTTP_AUTHORIZATION=make_auth_line("U0", "U0PASS"),
|
||||
)
|
||||
data = response.content.decode("utf-8")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
entries = json.loads(data)
|
||||
|
||||
acc_bal = SignedAmount(True, Amount(settings.TALER_CURRENCY, 10, 0))
|
||||
|
||||
for entry in reversed(entries["data"]):
|
||||
if entry["sign"] == "-":
|
||||
acc_bal += SignedAmount.parse(entry["amount"])
|
||||
if entry["sign"] == "+":
|
||||
acc_bal -= SignedAmount.parse(entry["amount"])
|
||||
|
||||
expected_amount = SignedAmount.parse(f"{settings.TALER_CURRENCY}:16.0")
|
||||
self.assertEqual(acc_bal, expected_amount)
|
|
@ -0,0 +1,144 @@
|
|||
# This file is part of TALER
|
||||
# (C) 2014, 2015, 2016 Taler Systems SA
|
||||
#
|
||||
# TALER 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, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# @author Marcello Stanisci
|
||||
# @author Florian Dold
|
||||
|
||||
from django.urls import include, path
|
||||
from django.views.generic.base import RedirectView
|
||||
from django.contrib.auth import views as auth_views
|
||||
from django.conf.urls.i18n import i18n_patterns
|
||||
from . import views
|
||||
|
||||
# These paths are part of the GNU Taler wire gatweay API
|
||||
taler_wire_gateway_patterns = [
|
||||
path("<str:acct_id>/", views.twg_base, name="twg-base"),
|
||||
path("<str:acct_id>/config", views.twg_config, name="twg-config"),
|
||||
path(
|
||||
"<str:acct_id>/admin/add-incoming",
|
||||
views.twg_add_incoming,
|
||||
name="twg-add-incoming",
|
||||
),
|
||||
path(
|
||||
"<str:acct_id>/history/incoming",
|
||||
views.twg_history_incoming,
|
||||
name="twg-history-incoming",
|
||||
),
|
||||
path(
|
||||
"<str:acct_id>/history/outgoing",
|
||||
views.twg_history_outgoing,
|
||||
name="twg-history-outgoing",
|
||||
),
|
||||
path("<str:acct_id>/transfer", views.twg_transfer, name="twg-transfer"),
|
||||
]
|
||||
|
||||
|
||||
taler_bank_integration_api_patterns = [
|
||||
path("api/config", views.api_config, name="api-config"),
|
||||
path(
|
||||
"api/withdrawal-operation/<str:withdraw_id>",
|
||||
views.api_withdraw_operation,
|
||||
name="api-withdraw-operation",
|
||||
),
|
||||
]
|
||||
|
||||
# These paths are part of the bank access API
|
||||
taler_bank_access_api_patterns = [
|
||||
path(
|
||||
"accounts/<str:acct_id>",
|
||||
views.bank_accounts_api_balance,
|
||||
name="access-api-balance",
|
||||
),
|
||||
path(
|
||||
"accounts/<str:acct_id>/withdrawals",
|
||||
views.bank_accounts_api_create_withdrawal,
|
||||
name="access-api-withdrawal",
|
||||
),
|
||||
path(
|
||||
"accounts/<str:acct_id>/withdrawals/<str:wid>",
|
||||
views.bank_accounts_api_get_withdrawal,
|
||||
name="access-api-withdrawal-status",
|
||||
),
|
||||
path(
|
||||
"accounts/<str:acct_id>/withdrawals/<str:wid>/confirm",
|
||||
views.bank_accounts_api_confirm_withdrawal,
|
||||
name="access-api-withdrawal-confirm",
|
||||
),
|
||||
path(
|
||||
"accounts/<str:acct_id>/withdrawals/<str:wid>/abort",
|
||||
views.bank_accounts_api_abort_withdrawal,
|
||||
name="access-api-withdrawal-abort",
|
||||
),
|
||||
path("testing/withdraw", views.withdraw_headless, name="testing-withdraw"),
|
||||
path("testing/register", views.register_headless, name="testing-withdraw-register"),
|
||||
]
|
||||
|
||||
urlpatterns = [
|
||||
path("", include(taler_bank_integration_api_patterns)),
|
||||
path("", include(taler_bank_access_api_patterns)),
|
||||
path("taler-wire-gateway/", include(taler_wire_gateway_patterns)),
|
||||
path(
|
||||
"abort-withdrawal/<str:withdraw_id>",
|
||||
views.abort_withdrawal,
|
||||
name="abort-withdrawal",
|
||||
),
|
||||
path("favicon.ico", views.ignore),
|
||||
path("config", views.config_view, name="config"),
|
||||
path("history", views.serve_history, name="history"),
|
||||
path("payto-transfer", views.payto_transfer, name="payto-transfer"),
|
||||
]
|
||||
|
||||
urlpatterns += i18n_patterns(
|
||||
path(
|
||||
"confirm-withdrawal/<str:withdraw_id>",
|
||||
views.confirm_withdrawal,
|
||||
name="withdraw-confirm",
|
||||
),
|
||||
path("start-withdrawal", views.start_withdrawal, name="start-withdrawal"),
|
||||
path(
|
||||
"show-withdrawal/<str:withdraw_id>", views.show_withdrawal, name="withdraw-show"
|
||||
),
|
||||
path("", RedirectView.as_view(pattern_name="profile"), name="index"),
|
||||
path("logout", views.logout_view, name="logout"),
|
||||
path("register", views.register, name="register"),
|
||||
path("profile", views.profile_page, name="profile"),
|
||||
path("payto-form", views.payto_form, name="payto-form"),
|
||||
path("wiretransfer-form", views.wiretransfer_form, name="wiretransfer-form"),
|
||||
path(
|
||||
"login",
|
||||
auth_views.LoginView.as_view(
|
||||
template_name="login.html",
|
||||
authentication_form=views.TalerAuthenticationForm,
|
||||
),
|
||||
name="login",
|
||||
),
|
||||
path(
|
||||
"public-accounts",
|
||||
views.serve_public_accounts,
|
||||
name="public-accounts",
|
||||
),
|
||||
path(
|
||||
"public-accounts/<str:name>",
|
||||
views.serve_public_accounts,
|
||||
name="public-accounts",
|
||||
),
|
||||
path(
|
||||
"public-accounts/<str:name>/<int:page>",
|
||||
views.serve_public_accounts,
|
||||
name="public-accounts",
|
||||
),
|
||||
)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,180 @@
|
|||
##
|
||||
# This file is part of TALER
|
||||
# (C) 2017 Taler Systems SA
|
||||
#
|
||||
# TALER 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, or (at your option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not,
|
||||
# see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# @author Florian Dold
|
||||
# @file CLI tool to manage all the bank's tasks.
|
||||
|
||||
import argparse
|
||||
import django
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
import site
|
||||
import logging
|
||||
import inspect
|
||||
import click
|
||||
|
||||
from taler.util.talerconfig import TalerConfig
|
||||
from django.core.management import call_command
|
||||
|
||||
SITE_PACKAGES = os.path.abspath(os.path.dirname(__file__) + "/..")
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# No perfect match to our logging format, but good enough ...
|
||||
UWSGI_LOGFMT = "%(ltime) %(proto) %(method) %(uri) %(proto) => %(status)"
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "talerbank.settings")
|
||||
|
||||
# Argument to tell uWSGI to load the python plugin.
|
||||
# This hack is required, because on systems where the plugin is statically linked,
|
||||
# loading it causes an error.
|
||||
arg_load_python = "--if-not-plugin python --plugins python --endif".split(" ")
|
||||
|
||||
|
||||
@click.group(help="Manager script of Taler bank.")
|
||||
@click.pass_context
|
||||
@click.option(
|
||||
"--http-port",
|
||||
help="Set HTTP as the serving protocol (taking precedence over the config.), and set the port.",
|
||||
type=int,
|
||||
)
|
||||
@click.option("-c", "--config", help="Path to the config file.")
|
||||
@click.option("--with-db", help="Database connection string.")
|
||||
def cli(ctx, http_port, config, with_db):
|
||||
if with_db:
|
||||
os.environ.setdefault("TALER_BANK_ALTDB", with_db)
|
||||
if config:
|
||||
os.environ["TALER_CONFIG_FILE"] = config
|
||||
|
||||
ctx.obj = dict(http_port=http_port, config=config)
|
||||
|
||||
|
||||
@cli.command(help="Serve the bank")
|
||||
@click.pass_obj
|
||||
def serve(obj):
|
||||
# if --http-port option is found, then serve via HTTP.
|
||||
# Otherwise serve on whatever protocol is specified in the config.
|
||||
serve = "http"
|
||||
if not obj["http_port"]:
|
||||
TC = TalerConfig.from_file(os.environ.get("TALER_CONFIG_FILE"))
|
||||
serve = TC["bank"]["serve"].value_string(required=True).lower()
|
||||
|
||||
if serve == "http":
|
||||
return handle_serve_http(obj["http_port"])
|
||||
handle_serve_uwsgi()
|
||||
|
||||
|
||||
@cli.command(
|
||||
name="django",
|
||||
help="Invoke 'django' sub-commands",
|
||||
context_settings=dict(ignore_unknown_options=True),
|
||||
)
|
||||
@click.argument("args", nargs=-1, type=click.UNPROCESSED)
|
||||
def handle_django(args):
|
||||
django.setup()
|
||||
# always run 'migrate' first, in case a virgin db is being used.
|
||||
call_command("migrate")
|
||||
django_index = sys.argv.index("django")
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line([sys.argv[0] + " django"] + sys.argv[django_index + 1 :])
|
||||
|
||||
|
||||
def handle_serve_http(port):
|
||||
import django
|
||||
|
||||
django.setup()
|
||||
print("migrating")
|
||||
call_command("migrate")
|
||||
print("providing accounts")
|
||||
call_command("provide_accounts")
|
||||
print("checking")
|
||||
call_command("check")
|
||||
if port is None:
|
||||
TC = TalerConfig.from_file(os.environ.get("TALER_CONFIG_FILE"))
|
||||
port = TC["bank"]["http_port"].value_int(required=True)
|
||||
|
||||
httpspec = ":%d" % (port,)
|
||||
params = [
|
||||
"uwsgi",
|
||||
"uwsgi",
|
||||
*arg_load_python,
|
||||
"--static-map",
|
||||
"/static=%s/talerbank/app/static" % SITE_PACKAGES,
|
||||
"--die-on-term",
|
||||
"--no-orphans",
|
||||
"--master",
|
||||
"--http",
|
||||
httpspec,
|
||||
"--log-format",
|
||||
UWSGI_LOGFMT,
|
||||
"--module",
|
||||
"talerbank.wsgi",
|
||||
]
|
||||
os.execlp(*params)
|
||||
|
||||
|
||||
def handle_serve_uwsgi():
|
||||
django.setup()
|
||||
call_command("migrate")
|
||||
call_command("provide_accounts")
|
||||
call_command("check")
|
||||
TC = TalerConfig.from_file(os.environ.get("TALER_CONFIG_FILE"))
|
||||
serve_uwsgi = TC["bank"]["uwsgi_serve"].value_string(required=True).lower()
|
||||
params = [
|
||||
"uwsgi",
|
||||
"uwsgi",
|
||||
*arg_load_python,
|
||||
"--static-map",
|
||||
"/static=%s/talerbank/app/static" % SITE_PACKAGES,
|
||||
"--die-on-term",
|
||||
"--no-orphans",
|
||||
"--master",
|
||||
"--log-format",
|
||||
UWSGI_LOGFMT,
|
||||
"--module",
|
||||
"talerbank.wsgi",
|
||||
]
|
||||
if serve_uwsgi == "tcp":
|
||||
port = TC["bank"]["uwsgi_port"].value_int(required=True)
|
||||
spec = ":%d" % (port,)
|
||||
params.extend(["--socket", spec])
|
||||
else:
|
||||
spec = TC["bank"]["uwsgi_unixpath"].value_filename(required=True)
|
||||
mode = TC["bank"]["uwsgi_unixpath_mode"].value_filename(required=True)
|
||||
params.extend(["--socket", spec])
|
||||
params.extend(["--chmod-socket=" + mode])
|
||||
try:
|
||||
os.makedirs(os.path.dirname(spec), exist_ok=True)
|
||||
except FileNotFoundError:
|
||||
print(f"{spec} is not a valid file path.")
|
||||
sys.exit(1)
|
||||
logging.info("launching uwsgi with argv %s", params[1:])
|
||||
os.execlp(*params)
|
||||
|
||||
|
||||
@cli.command(help="Print config values.")
|
||||
def config():
|
||||
TC = TalerConfig.from_file(os.environ.get("TALER_CONFIG_FILE"))
|
||||
TC.dump()
|
||||
|
||||
def run():
|
||||
cli()
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
|
@ -0,0 +1,190 @@
|
|||
##
|
||||
# This file is part of TALER
|
||||
# (C) 2017 Taler Systems SA
|
||||
#
|
||||
# TALER 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, or (at your option) any later version.
|
||||
#
|
||||
# TALER 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 TALER; see the file COPYING. If not,
|
||||
# see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# @author Florian Dold
|
||||
# @brief Extends the Jinja2 API with custom functions.
|
||||
|
||||
import os
|
||||
import math
|
||||
import json
|
||||
from urllib.parse import urlparse
|
||||
from django.urls import reverse, get_script_prefix
|
||||
from django.conf import settings
|
||||
from jinja2 import Environment
|
||||
from django.utils.translation import gettext
|
||||
import markupsafe
|
||||
|
||||
|
||||
##
|
||||
# Check if a URL is absolute or not.
|
||||
#
|
||||
# @param urloc the URL to check.
|
||||
# @return True if the URL is absolute, False otherwise.
|
||||
def is_absolute(urloc):
|
||||
return bool(urlparse(urloc).netloc)
|
||||
|
||||
|
||||
##
|
||||
# Join URL components held in a list, taking care
|
||||
# of not having double slashes in the result.
|
||||
#
|
||||
# @param parts list of URL components.
|
||||
# @return the string made of the joined components
|
||||
def join_urlparts(*parts):
|
||||
ret = ""
|
||||
part = 0
|
||||
while part < len(parts):
|
||||
buf = parts[part]
|
||||
part += 1
|
||||
if ret.endswith("/"):
|
||||
buf = buf.lstrip("/")
|
||||
elif ret and not buf.startswith("/"):
|
||||
buf = "/" + buf
|
||||
ret += buf
|
||||
return ret
|
||||
|
||||
|
||||
##
|
||||
# Prefixes the argument with the location for static content.
|
||||
#
|
||||
# @param urloc the URL portion that should be prefixed; in
|
||||
# other words, this will be in final position in the
|
||||
# produced result.
|
||||
# @return the URL that picks @a urloc from the location for
|
||||
# static content.
|
||||
def static(urloc):
|
||||
if is_absolute(urloc):
|
||||
return urloc
|
||||
return join_urlparts(get_script_prefix(), settings.STATIC_URL, urloc)
|
||||
|
||||
|
||||
##
|
||||
# Helper function that fetches a value from the settings.
|
||||
#
|
||||
# @param name the name to lookup in the settings.
|
||||
# @return @a name's value as defined in the settings, or
|
||||
# a empty string otherwise.
|
||||
def settings_value(name):
|
||||
return getattr(settings, name, "")
|
||||
|
||||
|
||||
##
|
||||
# Fetch the URL given its "name".
|
||||
#
|
||||
# @param url_name URL's name as defined in urlargs.py
|
||||
# @param kwargs key-value list that will be appended
|
||||
# to the URL as the parameter=value pairs.
|
||||
def url(url_name, *args, **kwargs):
|
||||
# strangely, Django's 'reverse' function
|
||||
# takes a named parameter 'kwargs' instead
|
||||
# of real kwargs.
|
||||
return reverse(url_name, args=args, kwargs=kwargs)
|
||||
|
||||
|
||||
##
|
||||
# Helper function that reads a value from the environment.
|
||||
#
|
||||
# @param name env value to read
|
||||
# @return the value, or None if not found.
|
||||
def env_get(name, default=None):
|
||||
return os.environ.get(name, default)
|
||||
|
||||
|
||||
##
|
||||
# Jinja2 specific function used to activate the definitions
|
||||
# of this module.
|
||||
#
|
||||
# @param options opaque argument (?) given from the caller.
|
||||
# @return Jinja2-specific object that contains the new definitions.
|
||||
def is_valid_amount(amount):
|
||||
if math.isnan(amount.value):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def tojson(x):
|
||||
"""Convert object to json"""
|
||||
return json.dumps(x)
|
||||
|
||||
|
||||
##
|
||||
# Stringifies amount.
|
||||
#
|
||||
# @param amount amount object.
|
||||
# @return amount pretty string.
|
||||
def amount_stringify(amount):
|
||||
return amount.stringify(settings.TALER_DIGITS, pretty=True)
|
||||
|
||||
|
||||
def get_locale(url):
|
||||
parts = url.split('/', 2)
|
||||
if (2 >= len(parts)):
|
||||
# Totally unexpected path format, do not localize
|
||||
return "en"
|
||||
lang = parts[1]
|
||||
return lang
|
||||
|
||||
|
||||
all_languages = {
|
||||
"en": "English [en]",
|
||||
"ar": "Arabic [ar]",
|
||||
"zh_Hant": "Chinese [zh]",
|
||||
"fr": "French [fr]",
|
||||
"de": "German [de]",
|
||||
"hi": "Hindi [hi]",
|
||||
"it": "Italian [it]",
|
||||
"ja": "Japanese [ja]",
|
||||
"ko": "Korean [ko]",
|
||||
"pt": "Portuguese [pt]",
|
||||
"pt_BR": "Portuguese (Brazil) [pt_BR]",
|
||||
"ru": "Russian [ru]",
|
||||
"es": "Spanish [es]",
|
||||
"sv": "Swedish [sv]",
|
||||
"tr": "Turkish [tr]",
|
||||
}
|
||||
|
||||
|
||||
def context_processor(request):
|
||||
def getlang():
|
||||
return get_locale(request.path)
|
||||
|
||||
return dict(getlang=getlang)
|
||||
|
||||
|
||||
def environment(**options):
|
||||
env = Environment(**options)
|
||||
|
||||
gettext_markup = lambda *args, **kwargs: markupsafe.Markup(
|
||||
gettext(*args, **kwargs)
|
||||
)
|
||||
|
||||
env.globals.update({
|
||||
"static": static,
|
||||
"url": url,
|
||||
"settings_value": settings_value,
|
||||
"env": env_get,
|
||||
"is_valid_amount": is_valid_amount,
|
||||
"amount_stringify": amount_stringify,
|
||||
"tojson": tojson,
|
||||
"_": gettext_markup,
|
||||
"gettext": gettext_markup,
|
||||
"get_locale": get_locale,
|
||||
"getactive": lambda: "bank",
|
||||
"all_languages": all_languages,
|
||||
})
|
||||
return env
|
|
@ -0,0 +1,247 @@
|
|||
"""
|
||||
Django settings for talerbank.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.9/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.9/ref/settings/
|
||||
"""
|
||||
|
||||
import base64
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import urllib.parse
|
||||
from taler.util.talerconfig import TalerConfig, ConfigurationError
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
LOGGER.info(
|
||||
"DJANGO_SETTINGS_MODULE: %s" % os.environ.get("DJANGO_SETTINGS_MODULE")
|
||||
)
|
||||
|
||||
TC = TalerConfig.from_file(os.environ.get("TALER_CONFIG_FILE"))
|
||||
|
||||
# Build paths inside the project like this:
|
||||
# os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
|
||||
|
||||
SECRET_KEY = os.environ.get("TALER_BANK_SECRET_KEY", None)
|
||||
|
||||
if not SECRET_KEY:
|
||||
LOGGER.info(
|
||||
"secret key not configured in"
|
||||
" TALER_BANK_SECRET_KEY env variable,"
|
||||
" generating random secret"
|
||||
)
|
||||
SECRET_KEY = base64.b64encode(os.urandom(32)).decode("utf-8")
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
|
||||
if "demo" == os.environ.get("TALER_ENV_NAME"):
|
||||
DEBUG = False
|
||||
else:
|
||||
DEBUG = True
|
||||
|
||||
ADMIN_ENABLED = False
|
||||
|
||||
ALLOWED_HOSTS = ["*"]
|
||||
|
||||
LOGIN_URL = "login"
|
||||
|
||||
LOGIN_REDIRECT_URL = "index"
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"talerbank.app",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.locale.LocaleMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
"talerbank.app.middleware.ExceptionMiddleware",
|
||||
"talerbank.app.middleware.DecompressionMiddleware",
|
||||
]
|
||||
|
||||
TEMPLATES = [{
|
||||
"BACKEND":
|
||||
"django.template.backends.jinja2.Jinja2",
|
||||
"DIRS": [
|
||||
os.path.join(BASE_DIR, "talerbank/app/templates"),
|
||||
],
|
||||
"OPTIONS": {
|
||||
"environment": "talerbank.jinja2.environment",
|
||||
"context_processors": ["talerbank.jinja2.context_processor"],
|
||||
},
|
||||
}]
|
||||
|
||||
# Disable those, since they don't work with
|
||||
# jinja2 anyways.
|
||||
TEMPLATE_CONTEXT_PROCESSORS = []
|
||||
|
||||
WSGI_APPLICATION = "talerbank.wsgi.application"
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
|
||||
|
||||
DATABASES = {}
|
||||
|
||||
DBNAME = TC.value_string("bank", "database", required=True)
|
||||
DBNAME = os.environ.get("TALER_BANK_ALTDB", DBNAME)
|
||||
|
||||
# Tells Django to add a BigAutoField column to every table that
|
||||
# doesn't have a primary key explicitly defined. Such column will
|
||||
# then be the primary key.
|
||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||
|
||||
if not DBNAME:
|
||||
raise Exception("DB not specified (neither in config or as" "cli argument)")
|
||||
|
||||
LOGGER.info("dbname: %s" % DBNAME)
|
||||
|
||||
CHECK_DBSTRING_FORMAT = re.search(
|
||||
r"[a-z]+:///[a-z]+([\?][a-z]+=[a-z/]+)?", DBNAME
|
||||
)
|
||||
if not CHECK_DBSTRING_FORMAT:
|
||||
LOGGER.error(
|
||||
"Bad db string given '%s', respect the format"
|
||||
"'dbtype:///dbname'" % DBNAME
|
||||
)
|
||||
sys.exit(2)
|
||||
|
||||
DBCONFIG = {}
|
||||
# Maybe trust the parsing from urlparse?
|
||||
DB_URL = urllib.parse.urlparse(DBNAME)
|
||||
|
||||
if DB_URL.scheme not in ("postgres") or DB_URL.scheme == "":
|
||||
LOGGER.error("DB '%s' is not supported" % DB_URL.scheme)
|
||||
sys.exit(1)
|
||||
if DB_URL.scheme == "postgres":
|
||||
DBCONFIG["ENGINE"] = "django.db.backends.postgresql_psycopg2"
|
||||
DBCONFIG["NAME"] = DB_URL.path.lstrip("/")
|
||||
|
||||
if not DB_URL.netloc:
|
||||
P = urllib.parse.parse_qs(DB_URL.query)
|
||||
if ("host" not in P) or P["host"] == "":
|
||||
HOST = None
|
||||
else:
|
||||
HOST = P["host"][0]
|
||||
else:
|
||||
HOST = DB_URL.netloc
|
||||
|
||||
if HOST:
|
||||
DBCONFIG["HOST"] = HOST # Sockets directory.
|
||||
|
||||
DATABASES["default"] = DBCONFIG
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
"NAME":
|
||||
"django.contrib.auth.password_validation"
|
||||
".UserAttributeSimilarityValidator"
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation"
|
||||
".MinimumLengthValidator"
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation"
|
||||
".CommonPasswordValidator"
|
||||
},
|
||||
{
|
||||
"NAME":
|
||||
"django.contrib.auth.password_validation"
|
||||
".NumericPasswordValidator"
|
||||
},
|
||||
]
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.9/topics/i18n/
|
||||
|
||||
TIME_ZONE = "UTC"
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.9/howto/static-files/
|
||||
|
||||
STATIC_URL = "/static/"
|
||||
|
||||
STATICFILES_DIRS = [
|
||||
os.path.join(BASE_DIR, "talerbank/app/static"),
|
||||
]
|
||||
|
||||
STATIC_ROOT = None
|
||||
ROOT_URLCONF = "talerbank.urls"
|
||||
|
||||
try:
|
||||
TALER_CURRENCY = TC.value_string("taler", "currency", required=True)
|
||||
except ConfigurationError as exc:
|
||||
LOGGER.error(exc)
|
||||
sys.exit(3)
|
||||
|
||||
TALER_MAX_DEBT = TC.value_string(
|
||||
"bank", "MAX_DEBT", default="%s:50.0" % TALER_CURRENCY
|
||||
)
|
||||
TALER_MAX_DEBT_BANK = TC.value_string(
|
||||
"bank", "MAX_DEBT_BANK", default="%s:0.0" % TALER_CURRENCY
|
||||
)
|
||||
|
||||
TALER_DIGITS = TC.value_int("bank", "NDIGITS", default=2)
|
||||
# Order matters
|
||||
TALER_PREDEFINED_ACCOUNTS = [
|
||||
"Bank",
|
||||
"Exchange",
|
||||
"blog",
|
||||
"Tor",
|
||||
"GNUnet",
|
||||
"Taler",
|
||||
"FSF",
|
||||
"Tutorial",
|
||||
"Survey",
|
||||
]
|
||||
TALER_EXPECTS_DONATIONS = ["Tor", "GNUnet", "Taler", "FSF"]
|
||||
TALER_SUGGESTED_EXCHANGE = TC.value_string("bank", "suggested_exchange")
|
||||
TALER_SUGGESTED_EXCHANGE_PAYTO = TC.value_string(
|
||||
"bank", "suggested_exchange_payto"
|
||||
)
|
||||
|
||||
_allow_reg = TC.value_string("bank", "ALLOW_REGISTRATIONS", default="no")
|
||||
|
||||
if _allow_reg.lower() == "yes":
|
||||
ALLOW_REGISTRATIONS = True
|
||||
else:
|
||||
ALLOW_REGISTRATIONS = False
|
||||
|
||||
_show_freeform_withdrawal = TC.value_string(
|
||||
"bank", "SHOW_FREEFORM_WITHDRAWAL", default="no"
|
||||
)
|
||||
if _show_freeform_withdrawal.lower() == "yes":
|
||||
SHOW_FREEFORM_WITHDRAWAL = True
|
||||
else:
|
||||
SHOW_FREEFORM_WITHDRAWAL = False
|
|
@ -0,0 +1,21 @@
|
|||
"""
|
||||
Taler Bank URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/1.9/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.conf.urls import url, include
|
||||
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||
from django.conf.urls import url
|
||||
from .app.urls import urlpatterns as app_urlpatterns
|
||||
|
||||
urlpatterns = staticfiles_urlpatterns() + app_urlpatterns
|
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
WSGI config for bank_project project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "talerbank.settings")
|
||||
|
||||
application = get_wsgi_application()
|
Loading…
Reference in New Issue