Merge branch 'master' into advanced-permissions-phase-1

Этот коммит содержится в:
George Goldberg
2018-02-06 17:25:53 +00:00
родитель e1cd646135 034dbc07e3
Коммит 7941c30117
1622 изменённых файлов: 185031 добавлений и 26488 удалений

Просмотреть файл

@@ -13,51 +13,63 @@ The one exception may be around release time, where the review process may take
After a PR is submitted, a core committer applies labels and notifies product managers (PMs) that there is a PR awaiting review by posting in the [PM/Docs PR Review channel](https://pre-release.mattermost.com/core/channels/pmdocs-pr-review-pub), which is a channel to discuss community pull requests that need review by PMs.
Then, one or more of the labels is applied:
- `Awaiting PR`: Applied if the PR is awaiting another to be merged. For example, when a client PR is awaiting a server PR to be merged first. Once the PR is no longer blocked, the core committer removes the `Awaiting PR` label
- `1: PM Review`: Applied if the PR has UI changes or functionality that PMs can test on test servers called "spinmints"
- `Major Change`: Applied if the PR is a major feature or affects large areas of the code base, e.g. [moving channel store and actions to Redux](https://github.com/mattermost/platform/pull/6235)
- `Setup Test Server`: Applied if the PR is queued for PM testing
- `Work in Progress`: Applied if the PR is unfinished and needs further work before it's ready for review
- `Awaiting PR`: Applied if the PR is awaiting another to be merged. For example, when a client PR is awaiting a server PR to be merged first. Once the PR is no longer blocked, the core committer removes the `Awaiting PR` label.
- `1: PM Review`: Applied if the PR has UI changes or functionality that PMs can test on test servers called "spinmints".
- `Major Change`: Applied if the PR is a major feature or affects large areas of the code base, e.g. [moving channel store and actions to Redux](https://github.com/mattermost/platform/pull/6235).
- `Setup Test Server`: Applied if the PR is queued for PM testing.
- `Work in Progress`: Applied if the PR is unfinished and needs further work before it's ready for review.
#### Stage 1: PM Review
A product manager will review the pull request to make sure it:
A product manager (PM) will review the pull request to make sure it:
- Fits with our product roadmap.
- Works as described in the ticket.
- Meets [user experience guidelines](https://docs.mattermost.com/developer/fx-guidelines.html).
- Fits with our product roadmap
- Works as described in the ticket
- Meets [user experience guidelines](https://docs.mattermost.com/developer/fx-guidelines.html)
This step is sometimes skipped for bugs or small improvements with a well-defined ticket. In this case the core committer will assign the appropriate devs for review. A PM can also ask developer support to set up a separate test instance if the PR cannot be easily tested.
This step is sometimes skipped for bugs or small improvements with a well defined ticket.
When the review process begins:
- Mattermost Core Committer
- Assigns `1: PM Review` label within 1 business day after the PR is submitted.
- Assigns PM reviewer under Assignees. Those related to end user features are assigned to @esethna, others to @jasonblais. PM re-assigns as needed.
- PM
- Applies milestone for next release if the PM thinks there is enough time for the PR to be merged and sufficiently tested on `master` before code complete. Otherwise moved to a future release, letting submitter know that PR may have a delay in review due to the release cycle.
- Follows up with contributor if the CLA has not been signed. If no response within 7 days, PM closes the issue.
- PM verifies there is a corresponding JIRA ticket or GitHub issue.
When the review process begins, the PM applies a milestone:
- Set for next release if the PM thinks there is enough time for the PR to be merged and sufficiently tested on `master` before code complete.
- Set for a future release if PR is too large to test prior to the code complete date
- PM responds to submitter letting them know that PR may have a delay in review due to the release cycle
Next, the PM tests changes on the spinmint:
Next, the PM tests changes on a spinmint test server:
- PM tests and verifies pull requests via the `Setup Test Server` label. Initial review is completed within 2 business days.
- If changes are required, PM submits review as "Changes Requested", with a comment on the areas that require updates. Comment explains why changes are needed linking back to design principles.
- PM applies `Awaiting Submitter Action` label to more easily query the PR queue
- PM applies `Awaiting Submitter Action` label to more easily query the PR queue.
- Once changes are made, PM regenerates test server and repeats testing.
- If bugs are found that are also on `master`, a new bug report is submitted in JIRA and linked to the PR. Bugs that are also found on `master` will typically not block merging of PRs.
- If PR is approved, PM submits review as "Approved" commenting with areas that were tested. Then:
- PM removes `1: PM Review` and `Setup Test Server` labels
- PM applies the `Stage 2: Dev Review` label, which moves the PR to Stage 2
- If PR is approved, PM submits review as "Approved", commenting with areas that were tested.
#### Stage 2: Dev Review
Two developers will review the pull request and either give feedback or approve the PR. If changes are required:
- Dev submits review as "Changes Requested", with a comment on the areas that require tweaks.
- Once changes are made, dev reviews code changes
Two developers will review the pull request and either give feedback or approve the PR. Any comments should be addressed before the pull request moves on to the next stage.
Any comments should be addressed before the pull request moves on to the last stage.
- PM reviewer adds `2: Dev Review` label, removes `1: PM Review` and `Setup Test Server` labels, and assigns 2 developers for review under Reviewers.
- At least one dev is assigned based on their [feature area](https://docs.mattermost.com/developer/core-developer-handbook.html#current-core-developers). Devs re-assign as needed.
- Devs review the code and provide feedback, with initial review completed within 2 business days. Some areas to check include:
- Proper Unit Tests
- API documentation
- Localization
- After the submitter has addressed and satisfied all reviewers' comments, `3: Ready to Merge` label is applied.
#### Stage 3: Ready to Merge
The review process is complete, and the pull request will be merged.
Review process is complete and the pull request is merged.
- Dev assigns `3: Ready to Merge` label.
- If Mattermost is not in release mode (between [major feature cut and release candidate cut](https://docs.mattermost.com/process/release-process.html), the PR is merged into `master`.
- If the PR is a major change, merge is postponed until the next release cycle.
- Dev calls out on the issue that it is a major change and it will be merged after branching.
- Once the current release is branched the PR can be merged into `master`.
#### PR Merged
After a PR is merged:
- External Contributions: PM closes the [Help Wanted] issue and related Jira ticket
- Internal Contributions: Core committer resolves the JIRA ticket
- PM follows up for docs, changelog and release tests when working through the PR tracking spreadsheet
- External Contributions: PM closes the [Help Wanted] issue and related JIRA ticket.
- Internal Contributions: Core committer resolves the JIRA ticket.
- PM follows up for docs and changelog, and QA for release tests.

Просмотреть файл

@@ -380,6 +380,15 @@ cover: ## Runs the golang coverage tool. You must run the unit tests first.
$(GO) tool cover -html=cover.out
$(GO) tool cover -html=ecover.out
test-data: start-docker ## Add test data to the local instance.
$(GO) run $(GOFLAGS) $(GO_LINKER_FLAGS) $(PLATFORM_FILES) sampledata -w 1
@echo You may need to restart the Mattermost server before using the following
@echo ====================================================================================
@echo Login with a system admin account email=user-0@sample.mattermost.com password=user-0
@echo Login with a regular account email=user-1@sample.mattermost.com password=user-1
@echo ====================================================================================
run-server: start-docker ## Starts the server.
@echo Running mattermost for development
@@ -468,7 +477,7 @@ clean: stop-docker ## Clean up everything except persistant server data.
cd $(BUILD_WEBAPP_DIR) && $(MAKE) clean
find . -type d -name data | xargs rm -r
find . -type d -name data -not -path './vendor/*' | xargs rm -r
rm -rf logs
rm -f mattermost.log

Просмотреть файл

@@ -2492,45 +2492,6 @@ limitations under the License.
---
This product contains a modified portion of pflag, a Commander for modern Go CLI interactions, built by Alex Ogier.
* HOMEPAGE:
* https://github.com/spf13/pflag
* LICENSE:
Copyright (c) 2012 Alex Ogier. All rights reserved.
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
This product contains modified portions of Prometheus client_golang, which is the Go library for Prometheus. Prometheus is a systems and service monitoring system, started by Matt T. Proud and Julius Volz in 2012.
* HOMEPAGE:
@@ -2938,15 +2899,14 @@ SOFTWARE.
## uasurfer
This product contains a modified portion of `uasurfer`, a Golang library for parsing User-Agent strings.
This product contains a modified portion of `uasurfer`, a Golang library for parsing User-Agent strings, built by Avocet.
* HOMEPAGE
* https://github.com/avct/uasurfer
* LICENSE
Apache License
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@@ -3137,3 +3097,470 @@ This product contains a modified portion of `uasurfer`, a Golang library for par
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---
## fake
Fake is a fake data generator for Go (Golang), heavily inspired by the forgery and ffaker Ruby gems, built by Dmitry Afanasyev.
* HOMEPAGE:
* https://github.com/icrowley/fake
* LICENSE:
The MIT License (MIT)
Copyright (c) 2014 Dmitry Afanasyev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
## memberlist
memberlist is a Go library that manages cluster membership and member failure detection using a gossip based protocol, built by HashiCorp.
* HOMEPAGE
* github.com/hashicorp/memberlist
* LICENSE
Mozilla Public License, version 2.0
1. Definitions
1.1. “Contributor”
means each individual or legal entity that creates, contributes to the
creation of, or owns Covered Software.
1.2. “Contributor Version”
means the combination of the Contributions of others (if any) used by a
Contributor and that particular Contributors Contribution.
1.3. “Contribution”
means Covered Software of a particular Contributor.
1.4. “Covered Software”
means Source Code Form to which the initial Contributor has attached the
notice in Exhibit A, the Executable Form of such Source Code Form, and
Modifications of such Source Code Form, in each case including portions
thereof.
1.5. “Incompatible With Secondary Licenses”
means
a. that the initial Contributor has attached the notice described in
Exhibit B to the Covered Software; or
b. that the Covered Software was made available under the terms of version
1.1 or earlier of the License, but not also under the terms of a
Secondary License.
1.6. “Executable Form”
means any form of the work other than Source Code Form.
1.7. “Larger Work”
means a work that combines Covered Software with other material, in a separate
file or files, that is not Covered Software.
1.8. “License”
means this document.
1.9. “Licensable”
means having the right to grant, to the maximum extent possible, whether at the
time of the initial grant or subsequently, any and all of the rights conveyed by
this License.
1.10. “Modifications”
means any of the following:
a. any file in Source Code Form that results from an addition to, deletion
from, or modification of the contents of Covered Software; or
b. any new file in Source Code Form that contains any Covered Software.
1.11. “Patent Claims” of a Contributor
means any patent claim(s), including without limitation, method, process,
and apparatus claims, in any patent Licensable by such Contributor that
would be infringed, but for the grant of the License, by the making,
using, selling, offering for sale, having made, import, or transfer of
either its Contributions or its Contributor Version.
1.12. “Secondary License”
means either the GNU General Public License, Version 2.0, the GNU Lesser
General Public License, Version 2.1, the GNU Affero General Public
License, Version 3.0, or any later versions of those licenses.
1.13. “Source Code Form”
means the form of the work preferred for making modifications.
1.14. “You” (or “Your”)
means an individual or a legal entity exercising rights under this
License. For legal entities, “You” includes any entity that controls, is
controlled by, or is under common control with You. For purposes of this
definition, “control” means (a) the power, direct or indirect, to cause
the direction or management of such entity, whether by contract or
otherwise, or (b) ownership of more than fifty percent (50%) of the
outstanding shares or beneficial ownership of such entity.
2. License Grants and Conditions
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
a. under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or as
part of a Larger Work; and
b. under Patent Claims of such Contributor to make, use, sell, offer for
sale, have made, import, and otherwise transfer either its Contributions
or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution become
effective for each Contribution on the date the Contributor first distributes
such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under this
License. No additional rights or licenses will be implied from the distribution
or licensing of Covered Software under this License. Notwithstanding Section
2.1(b) above, no patent license is granted by a Contributor:
a. for any code that a Contributor has removed from Covered Software; or
b. for infringements caused by: (i) Your and any other third partys
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
c. under Patent Claims infringed by Covered Software in the absence of its
Contributions.
This License does not grant any rights in the trademarks, service marks, or
logos of any Contributor (except as may be necessary to comply with the
notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this License
(see Section 10.2) or under the terms of a Secondary License (if permitted
under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its Contributions
are its original creation(s) or it has sufficient rights to grant the
rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under applicable
copyright doctrines of fair use, fair dealing, or other equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
Section 2.1.
3. Responsibilities
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under the
terms of this License. You must inform recipients that the Source Code Form
of the Covered Software is governed by the terms of this License, and how
they can obtain a copy of this License. You may not attempt to alter or
restrict the recipients rights in the Source Code Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
a. such Covered Software must also be made available in Source Code Form,
as described in Section 3.1, and You must inform recipients of the
Executable Form how they can obtain a copy of such Source Code Form by
reasonable means in a timely manner, at a charge no more than the cost
of distribution to the recipient; and
b. You may distribute such Executable Form under the terms of this License,
or sublicense it under different terms, provided that the license for
the Executable Form does not attempt to limit or alter the recipients
rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for the
Covered Software. If the Larger Work is a combination of Covered Software
with a work governed by one or more Secondary Licenses, and the Covered
Software is not Incompatible With Secondary Licenses, this License permits
You to additionally distribute such Covered Software under the terms of
such Secondary License(s), so that the recipient of the Larger Work may, at
their option, further distribute the Covered Software under the terms of
either this License or such Secondary License(s).
3.4. Notices
You may not remove or alter the substance of any license notices (including
copyright notices, patent notices, disclaimers of warranty, or limitations
of liability) contained within the Source Code Form of the Covered
Software, except that You may alter any license notices to the extent
required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on behalf
of any Contributor. You must make it absolutely clear that any such
warranty, support, indemnity, or liability obligation is offered by You
alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
If it is impossible for You to comply with any of the terms of this License
with respect to some or all of the Covered Software due to statute, judicial
order, or regulation then You must: (a) comply with the terms of this License
to the maximum extent possible; and (b) describe the limitations and the code
they affect. Such description must be placed in a text file included with all
distributions of the Covered Software under this License. Except to the
extent prohibited by statute or regulation, such description must be
sufficiently detailed for a recipient of ordinary skill to be able to
understand it.
5. Termination
5.1. The rights granted under this License will terminate automatically if You
fail to comply with any of its terms. However, if You become compliant,
then the rights granted under this License from a particular Contributor
are reinstated (a) provisionally, unless and until such Contributor
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
if such Contributor fails to notify You of the non-compliance by some
reasonable means prior to 60 days after You have come back into compliance.
Moreover, Your grants from a particular Contributor are reinstated on an
ongoing basis if such Contributor notifies You of the non-compliance by
some reasonable means, this is the first time You have received notice of
non-compliance with this License from such Contributor, and You become
compliant prior to 30 days after Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions, counter-claims,
and cross-claims) alleging that a Contributor Version directly or
indirectly infringes any patent, then the rights granted to You by any and
all Contributors for the Covered Software under Section 2.1 of this License
shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
license agreements (excluding distributors and resellers) which have been
validly granted by You or Your distributors under this License prior to
termination shall survive termination.
6. Disclaimer of Warranty
Covered Software is provided under this License on an “as is” basis, without
warranty of any kind, either expressed, implied, or statutory, including,
without limitation, warranties that the Covered Software is free of defects,
merchantable, fit for a particular purpose or non-infringing. The entire
risk as to the quality and performance of the Covered Software is with You.
Should any Covered Software prove defective in any respect, You (not any
Contributor) assume the cost of any necessary servicing, repair, or
correction. This disclaimer of warranty constitutes an essential part of this
License. No use of any Covered Software is authorized under this License
except under this disclaimer.
7. Limitation of Liability
Under no circumstances and under no legal theory, whether tort (including
negligence), contract, or otherwise, shall any Contributor, or anyone who
distributes Covered Software as permitted above, be liable to You for any
direct, indirect, special, incidental, or consequential damages of any
character including, without limitation, damages for lost profits, loss of
goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses, even if such party shall have been
informed of the possibility of such damages. This limitation of liability
shall not apply to liability for death or personal injury resulting from such
partys negligence to the extent applicable law prohibits such limitation.
Some jurisdictions do not allow the exclusion or limitation of incidental or
consequential damages, so this exclusion and limitation may not apply to You.
8. Litigation
Any litigation relating to this License may be brought only in the courts of
a jurisdiction where the defendant maintains its principal place of business
and such litigation shall be governed by laws of that jurisdiction, without
reference to its conflict-of-law provisions. Nothing in this Section shall
prevent a partys ability to bring cross-claims or counter-claims.
9. Miscellaneous
This License represents the complete agreement concerning the subject matter
hereof. If any provision of this License is held to be unenforceable, such
provision shall be reformed only to the extent necessary to make it
enforceable. Any law or regulation which provides that the language of a
contract shall be construed against the drafter shall not be used to construe
this License against a Contributor.
10. Versions of the License
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version of
the License under which You originally received the Covered Software, or
under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a modified
version of this License if you rename the license and remove any
references to the name of the license steward (except to note that such
modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular file, then
You may include the notice in a location (such as a LICENSE file in a relevant
directory) where a recipient would be likely to look for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - “Incompatible With Secondary Licenses” Notice
This Source Code Form is “Incompatible
With Secondary Licenses”, as defined by
the Mozilla Public License, v. 2.0.
---
## gorp
This product contains Go Relational Persistence, an ORM-ish library for Go.
* HOMEPAGE
* github.com/mattermost/gorp
* LICENSE
(The MIT License)
Copyright (c) 2012 James Cooper <james@bitmechanic.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
## errors
Package errors provides simple error handling primitives, built by pkg.
* HOMEPAGE
* github.com/pkg/errors
* LICENSE
Copyright (c) 2015, Dave Cheney <dave@cheney.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Просмотреть файл

@@ -114,40 +114,16 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
metrics.IncrementHttpRequest()
}
token := ""
isTokenFromQueryString := false
token, tokenLocation := app.ParseAuthTokenFromRequest(r)
// Attempt to parse token out of the header
authHeader := r.Header.Get(model.HEADER_AUTH)
if len(authHeader) > 6 && strings.ToUpper(authHeader[0:6]) == model.HEADER_BEARER {
// Default session token
token = authHeader[7:]
} else if len(authHeader) > 5 && strings.ToLower(authHeader[0:5]) == model.HEADER_TOKEN {
// OAuth token
token = authHeader[6:]
}
// Attempt to parse the token from the cookie
if len(token) == 0 {
if cookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil {
token = cookie.Value
if (h.requireSystemAdmin || h.requireUser) && !h.trustRequester {
if r.Header.Get(model.HEADER_REQUESTED_WITH) != model.HEADER_REQUESTED_WITH_XML {
c.Err = model.NewAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token+" Appears to be a CSRF attempt", http.StatusUnauthorized)
token = ""
}
}
// CSRF Check
if tokenLocation == app.TokenLocationCookie && (h.requireSystemAdmin || h.requireUser) && !h.trustRequester {
if r.Header.Get(model.HEADER_REQUESTED_WITH) != model.HEADER_REQUESTED_WITH_XML {
c.Err = model.NewAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token+" Appears to be a CSRF attempt", http.StatusUnauthorized)
token = ""
}
}
// Attempt to parse token out of the query string
if len(token) == 0 {
token = r.URL.Query().Get("access_token")
isTokenFromQueryString = true
}
c.SetSiteURLHeader(app.GetProtocol(r) + "://" + r.Host)
w.Header().Set(model.HEADER_REQUEST_ID, c.RequestId)
@@ -175,11 +151,16 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if h.requireUser || h.requireSystemAdmin {
c.Err = model.NewAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token, http.StatusUnauthorized)
}
} else if !session.IsOAuth && isTokenFromQueryString {
} else if !session.IsOAuth && tokenLocation == app.TokenLocationQueryString {
c.Err = model.NewAppError("ServeHTTP", "api.context.token_provided.app_error", nil, "token="+token, http.StatusUnauthorized)
} else {
c.Session = *session
}
// Rate limit by UserID
if c.App.Srv.RateLimiter != nil && c.App.Srv.RateLimiter.UserIdRateLimit(c.Session.UserId, w) {
return
}
}
if h.isApi || h.isTeamIndependent {

Просмотреть файл

@@ -1159,7 +1159,7 @@ func completeSaml(c *Context, w http.ResponseWriter, r *http.Request) {
}
return
} else {
if err := c.App.CheckUserAdditionalAuthenticationCriteria(user, ""); err != nil {
if err := c.App.CheckUserAllAuthenticationCriteria(user, ""); err != nil {
c.Err = err
c.Err.StatusCode = http.StatusFound
return

Просмотреть файл

@@ -16,6 +16,8 @@ import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/mattermost/mattermost-server/app"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/store"
@@ -187,7 +189,7 @@ func TestLogin(t *testing.T) {
}
if _, err := Client.Login(ruser2.Data.(*model.User).Email, user2.Password); err != nil {
t.Fatal("From verfied hash")
t.Fatal("From verified hash")
}
Client.AuthToken = authToken
@@ -199,14 +201,49 @@ func TestLogin(t *testing.T) {
Password: "passwd1",
AuthService: model.USER_AUTH_SERVICE_LDAP,
}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
store.Must(th.App.Srv.Store.User().VerifyEmail(user3.Id))
ruser3 := Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
store.Must(th.App.Srv.Store.User().VerifyEmail(ruser3.Id))
if _, err := Client.Login(user3.Id, user3.Password); err == nil {
if _, err := Client.Login(ruser3.Id, user3.Password); err == nil {
t.Fatal("AD/LDAP user should not be able to log in with AD/LDAP disabled")
}
}
func TestLoginUnverifiedEmail(t *testing.T) {
assert := assert.New(t)
th := Setup().InitBasic()
defer th.TearDown()
Client := th.BasicClient
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.EmailSettings.EnableSignInWithEmail = true
cfg.EmailSettings.RequireEmailVerification = true
})
Client.Logout()
user := &model.User{
Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com",
Nickname: "Corey Hulen",
Username: "corey" + model.NewId(),
Password: "passwd1",
EmailVerified: false,
}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
_, err := Client.Login(user.Email, user.Password+"invalid")
if assert.NotNil(err) {
assert.Equal("api.user.check_user_password.invalid.app_error", err.Id)
}
_, err = Client.Login(user.Email, "passwd1")
if assert.NotNil(err) {
assert.Equal("api.user.login.not_verified.app_error", err.Id)
}
}
func TestLoginByLdap(t *testing.T) {
th := Setup().InitBasic()
defer th.TearDown()

Просмотреть файл

@@ -21,6 +21,7 @@ func (api *API) InitChannel() {
api.BaseRoutes.ChannelsForTeam.Handle("/deleted", api.ApiSessionRequired(getDeletedChannelsForTeam)).Methods("GET")
api.BaseRoutes.ChannelsForTeam.Handle("/ids", api.ApiSessionRequired(getPublicChannelsByIdsForTeam)).Methods("POST")
api.BaseRoutes.ChannelsForTeam.Handle("/search", api.ApiSessionRequired(searchChannelsForTeam)).Methods("POST")
api.BaseRoutes.ChannelsForTeam.Handle("/autocomplete", api.ApiSessionRequired(autocompleteChannelsForTeam)).Methods("GET")
api.BaseRoutes.User.Handle("/teams/{team_id:[A-Za-z0-9]+}/channels", api.ApiSessionRequired(getChannelsForTeamForUser)).Methods("GET")
api.BaseRoutes.Channel.Handle("", api.ApiSessionRequired(getChannel)).Methods("GET")
@@ -490,6 +491,27 @@ func getChannelsForTeamForUser(c *Context, w http.ResponseWriter, r *http.Reques
}
}
func autocompleteChannelsForTeam(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireTeamId()
if c.Err != nil {
return
}
if !c.App.SessionHasPermissionToTeam(c.Session, c.Params.TeamId, model.PERMISSION_LIST_TEAM_CHANNELS) {
c.SetPermissionError(model.PERMISSION_LIST_TEAM_CHANNELS)
return
}
name := r.URL.Query().Get("name")
if channels, err := c.App.AutocompleteChannels(c.Params.TeamId, name); err != nil {
c.Err = err
return
} else {
w.Write([]byte(channels.ToJson()))
}
}
func searchChannelsForTeam(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireTeamId()
if c.Err != nil {

Просмотреть файл

@@ -99,40 +99,16 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c.IpAddress = utils.GetIpAddress(r)
c.Params = ApiParamsFromRequest(r)
token := ""
isTokenFromQueryString := false
token, tokenLocation := app.ParseAuthTokenFromRequest(r)
// Attempt to parse token out of the header
authHeader := r.Header.Get(model.HEADER_AUTH)
if len(authHeader) > 6 && strings.ToUpper(authHeader[0:6]) == model.HEADER_BEARER {
// Default session token
token = authHeader[7:]
} else if len(authHeader) > 5 && strings.ToLower(authHeader[0:5]) == model.HEADER_TOKEN {
// OAuth token
token = authHeader[6:]
}
// Attempt to parse the token from the cookie
if len(token) == 0 {
if cookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil {
token = cookie.Value
if h.requireSession && !h.trustRequester {
if r.Header.Get(model.HEADER_REQUESTED_WITH) != model.HEADER_REQUESTED_WITH_XML {
c.Err = model.NewAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token+" Appears to be a CSRF attempt", http.StatusUnauthorized)
token = ""
}
}
// CSRF Check
if tokenLocation == app.TokenLocationCookie && h.requireSession && !h.trustRequester {
if r.Header.Get(model.HEADER_REQUESTED_WITH) != model.HEADER_REQUESTED_WITH_XML {
c.Err = model.NewAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token+" Appears to be a CSRF attempt", http.StatusUnauthorized)
token = ""
}
}
// Attempt to parse token out of the query string
if len(token) == 0 {
token = r.URL.Query().Get("access_token")
isTokenFromQueryString = true
}
c.SetSiteURLHeader(app.GetProtocol(r) + "://" + r.Host)
w.Header().Set(model.HEADER_REQUEST_ID, c.RequestId)
@@ -153,11 +129,16 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if h.requireSession {
c.Err = model.NewAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token, http.StatusUnauthorized)
}
} else if !session.IsOAuth && isTokenFromQueryString {
} else if !session.IsOAuth && tokenLocation == app.TokenLocationQueryString {
c.Err = model.NewAppError("ServeHTTP", "api.context.token_provided.app_error", nil, "token="+token, http.StatusUnauthorized)
} else {
c.Session = *session
}
// Rate limit by UserID
if c.App.Srv.RateLimiter != nil && c.App.Srv.RateLimiter.UserIdRateLimit(c.Session.UserId, w) {
return
}
}
c.Path = r.URL.Path

Просмотреть файл

@@ -11,6 +11,30 @@ import (
"github.com/mattermost/mattermost-server/utils"
)
type TokenLocation int
const (
TokenLocationNotFound = iota
TokenLocationHeader
TokenLocationCookie
TokenLocationQueryString
)
func (tl TokenLocation) String() string {
switch tl {
case TokenLocationNotFound:
return "Not Found"
case TokenLocationHeader:
return "Header"
case TokenLocationCookie:
return "Cookie"
case TokenLocationQueryString:
return "QueryString"
default:
return "Unknown"
}
}
func (a *App) IsPasswordValid(password string) *model.AppError {
if utils.IsLicensed() && *utils.License().Features.PasswordRequirements {
return utils.IsPasswordValidWithSettings(password, &a.Config().PasswordSettings)
@@ -19,7 +43,7 @@ func (a *App) IsPasswordValid(password string) *model.AppError {
}
func (a *App) CheckPasswordAndAllCriteria(user *model.User, password string, mfaToken string) *model.AppError {
if err := a.CheckUserAdditionalAuthenticationCriteria(user, mfaToken); err != nil {
if err := a.CheckUserPreflightAuthenticationCriteria(user, mfaToken); err != nil {
return err
}
@@ -27,6 +51,10 @@ func (a *App) CheckPasswordAndAllCriteria(user *model.User, password string, mfa
return err
}
if err := a.CheckUserPostflightAuthenticationCriteria(user); err != nil {
return err
}
return nil
}
@@ -85,13 +113,21 @@ func (a *App) checkLdapUserPasswordAndAllCriteria(ldapId *string, password strin
return user, nil
}
func (a *App) CheckUserAdditionalAuthenticationCriteria(user *model.User, mfaToken string) *model.AppError {
if err := a.CheckUserMfa(user, mfaToken); err != nil {
func (a *App) CheckUserAllAuthenticationCriteria(user *model.User, mfaToken string) *model.AppError {
if err := a.CheckUserPreflightAuthenticationCriteria(user, mfaToken); err != nil {
return err
}
if !user.EmailVerified && a.Config().EmailSettings.RequireEmailVerification {
return model.NewAppError("Login", "api.user.login.not_verified.app_error", nil, "user_id="+user.Id, http.StatusUnauthorized)
if err := a.CheckUserPostflightAuthenticationCriteria(user); err != nil {
return err
}
return nil
}
func (a *App) CheckUserPreflightAuthenticationCriteria(user *model.User, mfaToken string) *model.AppError {
if err := a.CheckUserMfa(user, mfaToken); err != nil {
return err
}
if err := checkUserNotDisabled(user); err != nil {
@@ -105,6 +141,14 @@ func (a *App) CheckUserAdditionalAuthenticationCriteria(user *model.User, mfaTok
return nil
}
func (a *App) CheckUserPostflightAuthenticationCriteria(user *model.User) *model.AppError {
if !user.EmailVerified && a.Config().EmailSettings.RequireEmailVerification {
return model.NewAppError("Login", "api.user.login.not_verified.app_error", nil, "user_id="+user.Id, http.StatusUnauthorized)
}
return nil
}
func (a *App) CheckUserMfa(user *model.User, token string) *model.AppError {
if !user.MfaActive || !utils.IsLicensed() || !*utils.License().Features.MFA || !*a.Config().ServiceSettings.EnableMultifactorAuthentication {
return nil
@@ -168,3 +212,26 @@ func (a *App) authenticateUser(user *model.User, password, mfaToken string) (*mo
}
}
}
func ParseAuthTokenFromRequest(r *http.Request) (string, TokenLocation) {
authHeader := r.Header.Get(model.HEADER_AUTH)
if len(authHeader) > 6 && strings.ToUpper(authHeader[0:6]) == model.HEADER_BEARER {
// Default session token
return authHeader[7:], TokenLocationHeader
} else if len(authHeader) > 5 && strings.ToLower(authHeader[0:5]) == model.HEADER_TOKEN {
// OAuth token
return authHeader[6:], TokenLocationHeader
}
// Attempt to parse the token from the cookie
if cookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil {
return cookie.Value, TokenLocationCookie
}
// Attempt to parse token out of the query string
if token := r.URL.Query().Get("access_token"); token != "" {
return token, TokenLocationQueryString
}
return "", TokenLocationNotFound
}

52
app/authentication_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,52 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
import (
"net/http"
"net/http/httptest"
"strconv"
"testing"
"github.com/mattermost/mattermost-server/model"
"github.com/stretchr/testify/require"
)
func TestParseAuthTokenFromRequest(t *testing.T) {
cases := []struct {
header string
cookie string
query string
expectedToken string
expectedLocation TokenLocation
}{
{"", "", "", "", TokenLocationNotFound},
{"token mytoken", "", "", "mytoken", TokenLocationHeader},
{"BEARER mytoken", "", "", "mytoken", TokenLocationHeader},
{"", "mytoken", "", "mytoken", TokenLocationCookie},
{"", "", "mytoken", "mytoken", TokenLocationQueryString},
}
for testnum, tc := range cases {
pathname := "/test/here"
if tc.query != "" {
pathname += "?access_token=" + tc.query
}
req := httptest.NewRequest("GET", pathname, nil)
if tc.header != "" {
req.Header.Add(model.HEADER_AUTH, tc.header)
}
if tc.cookie != "" {
req.AddCookie(&http.Cookie{
Name: model.SESSION_COOKIE_TOKEN,
Value: tc.cookie,
})
}
token, location := ParseAuthTokenFromRequest(req)
require.Equal(t, tc.expectedToken, token, "Wrong token on test "+strconv.Itoa(testnum))
require.Equal(t, tc.expectedLocation, location, "Wrong location on test "+strconv.Itoa(testnum))
}
}

Просмотреть файл

@@ -1259,6 +1259,14 @@ func (a *App) UpdateChannelLastViewedAt(channelIds []string, userId string) *mod
return nil
}
func (a *App) AutocompleteChannels(teamId string, term string) (*model.ChannelList, *model.AppError) {
if result := <-a.Srv.Store.Channel().AutocompleteInTeam(teamId, term); result.Err != nil {
return nil, result.Err
} else {
return result.Data.(*model.ChannelList), nil
}
}
func (a *App) SearchChannels(teamId string, term string) (*model.ChannelList, *model.AppError) {
if result := <-a.Srv.Store.Channel().SearchInTeam(teamId, term); result.Err != nil {
return nil, result.Err

Просмотреть файл

@@ -241,6 +241,9 @@ func (a *App) trackConfig() {
"enable_tutorial": *cfg.ServiceSettings.EnableTutorial,
"experimental_enable_default_channel_leave_join_messages": *cfg.ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages,
"experimental_group_unread_channels": *cfg.ServiceSettings.ExperimentalGroupUnreadChannels,
"isdefault_image_proxy_type": isDefault(*cfg.ServiceSettings.ImageProxyType, ""),
"isdefault_image_proxy_url": isDefault(*cfg.ServiceSettings.ImageProxyURL, ""),
"isdefault_image_proxy_options": isDefault(*cfg.ServiceSettings.ImageProxyOptions, ""),
})
a.SendDiagnostic(TRACK_CONFIG_TEAM, map[string]interface{}{
@@ -347,7 +350,8 @@ func (a *App) trackConfig() {
a.SendDiagnostic(TRACK_CONFIG_RATE, map[string]interface{}{
"enable_rate_limiter": *cfg.RateLimitSettings.Enable,
"vary_by_remote_address": cfg.RateLimitSettings.VaryByRemoteAddr,
"vary_by_remote_address": *cfg.RateLimitSettings.VaryByRemoteAddr,
"vary_by_user": *cfg.RateLimitSettings.VaryByUser,
"per_sec": *cfg.RateLimitSettings.PerSec,
"max_burst": *cfg.RateLimitSettings.MaxBurst,
"memory_store_size": *cfg.RateLimitSettings.MemoryStoreSize,

Просмотреть файл

@@ -584,16 +584,16 @@ func (a *App) sendPushNotification(post *model.Post, user *model.User, channel *
msg.ChannelName = channel.Name
msg.SenderId = post.UserId
if ou, ok := post.Props["override_username"]; ok && ou != nil {
msg.OverrideUsername = ou.(string)
if ou, ok := post.Props["override_username"].(string); ok {
msg.OverrideUsername = ou
}
if oi, ok := post.Props["override_icon_url"]; ok && oi != nil {
msg.OverrideIconUrl = oi.(string)
if oi, ok := post.Props["override_icon_url"].(string); ok {
msg.OverrideIconUrl = oi
}
if fw, ok := post.Props["from_webhook"]; ok && fw != nil {
msg.FromWebhook = fw.(string)
if fw, ok := post.Props["from_webhook"].(string); ok {
msg.FromWebhook = fw
}
if *a.Config().EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION {

Просмотреть файл

@@ -564,7 +564,7 @@ func generateOAuthStateTokenExtra(email, action, cookie string) string {
func (a *App) GetAuthorizationCode(w http.ResponseWriter, r *http.Request, service string, props map[string]string, loginHint string) (string, *model.AppError) {
sso := a.Config().GetSSOService(service)
if sso != nil && !sso.Enable {
if sso == nil || !sso.Enable {
return "", model.NewAppError("GetAuthorizationCode", "api.user.get_authorization_code.unsupported.app_error", nil, "service="+service, http.StatusNotImplemented)
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@@ -890,7 +890,7 @@ func (a *App) ImageProxyAdder() func(string) string {
}
return func(url string) string {
if strings.HasPrefix(url, proxyURL) {
if url == "" || strings.HasPrefix(url, proxyURL) {
return url
}

Просмотреть файл

@@ -211,6 +211,12 @@ func TestImageProxy(t *testing.T) {
ImageURL: "http://mydomain.com/myimage",
ProxiedImageURL: "https://127.0.0.1/x1000/http://mydomain.com/myimage",
},
"willnorris/imageproxy_EmptyImageURL": {
ProxyType: "willnorris/imageproxy",
ProxyURL: "https://127.0.0.1",
ImageURL: "",
ProxiedImageURL: "",
},
"willnorris/imageproxy_WithSigning": {
ProxyType: "willnorris/imageproxy",
ProxyURL: "https://127.0.0.1",

130
app/ratelimit.go Обычный файл
Просмотреть файл

@@ -0,0 +1,130 @@
// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
import (
"math"
"net/http"
"strconv"
"strings"
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/utils"
"github.com/pkg/errors"
throttled "gopkg.in/throttled/throttled.v2"
"gopkg.in/throttled/throttled.v2/store/memstore"
)
type RateLimiter struct {
throttledRateLimiter *throttled.GCRARateLimiter
useAuth bool
useIP bool
header string
}
func NewRateLimiter(settings *model.RateLimitSettings) (*RateLimiter, error) {
store, err := memstore.New(*settings.MemoryStoreSize)
if err != nil {
return nil, errors.Wrap(err, utils.T("api.server.start_server.rate_limiting_memory_store"))
}
quota := throttled.RateQuota{
MaxRate: throttled.PerSec(*settings.PerSec),
MaxBurst: *settings.MaxBurst,
}
throttledRateLimiter, err := throttled.NewGCRARateLimiter(store, quota)
if err != nil {
return nil, errors.Wrap(err, utils.T("api.server.start_server.rate_limiting_rate_limiter"))
}
return &RateLimiter{
throttledRateLimiter: throttledRateLimiter,
useAuth: *settings.VaryByUser,
useIP: *settings.VaryByRemoteAddr,
header: settings.VaryByHeader,
}, nil
}
func (rl *RateLimiter) GenerateKey(r *http.Request) string {
key := ""
if rl.useAuth {
token, tokenLocation := ParseAuthTokenFromRequest(r)
if tokenLocation != TokenLocationNotFound {
key += token
} else if rl.useIP { // If we don't find an authentication token and IP based is enabled, fall back to IP
key += utils.GetIpAddress(r)
}
} else if rl.useIP { // Only if Auth based is not enabed do we use a plain IP based
key += utils.GetIpAddress(r)
}
// Note that most of the time the user won't have to set this because the utils.GetIpAddress above tries the
// most common headers anyway.
if rl.header != "" {
key += strings.ToLower(r.Header.Get(rl.header))
}
return key
}
func (rl *RateLimiter) RateLimitWriter(key string, w http.ResponseWriter) bool {
limited, context, err := rl.throttledRateLimiter.RateLimit(key, 1)
if err != nil {
l4g.Critical("Internal server error when rate limiting. Rate Limiting broken. Error:" + err.Error())
return false
}
setRateLimitHeaders(w, context)
if limited {
l4g.Error("Denied due to throttling settings code=429 key=%v", key)
http.Error(w, "limit exceeded", 429)
}
return limited
}
func (rl *RateLimiter) UserIdRateLimit(userId string, w http.ResponseWriter) bool {
if rl.useAuth {
if rl.RateLimitWriter(userId, w) {
return true
}
}
return false
}
func (rl *RateLimiter) RateLimitHandler(wrappedHandler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
key := rl.GenerateKey(r)
limited := rl.RateLimitWriter(key, w)
if !limited {
wrappedHandler.ServeHTTP(w, r)
}
})
}
// Copied from https://github.com/throttled/throttled http.go
func setRateLimitHeaders(w http.ResponseWriter, context throttled.RateLimitResult) {
if v := context.Limit; v >= 0 {
w.Header().Add("X-RateLimit-Limit", strconv.Itoa(v))
}
if v := context.Remaining; v >= 0 {
w.Header().Add("X-RateLimit-Remaining", strconv.Itoa(v))
}
if v := context.ResetAfter; v >= 0 {
vi := int(math.Ceil(v.Seconds()))
w.Header().Add("X-RateLimit-Reset", strconv.Itoa(vi))
}
if v := context.RetryAfter; v >= 0 {
vi := int(math.Ceil(v.Seconds()))
w.Header().Add("Retry-After", strconv.Itoa(vi))
}
}

82
app/ratelimit_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,82 @@
// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
import (
"net/http"
"net/http/httptest"
"strconv"
"testing"
"github.com/mattermost/mattermost-server/model"
"github.com/stretchr/testify/require"
)
func genRateLimitSettings(useAuth, useIP bool, header string) *model.RateLimitSettings {
return &model.RateLimitSettings{
Enable: model.NewBool(true),
PerSec: model.NewInt(10),
MaxBurst: model.NewInt(100),
MemoryStoreSize: model.NewInt(10000),
VaryByRemoteAddr: model.NewBool(useIP),
VaryByUser: model.NewBool(useAuth),
VaryByHeader: header,
}
}
func TestNewRateLimiterSuccess(t *testing.T) {
settings := genRateLimitSettings(false, false, "")
rateLimiter, err := NewRateLimiter(settings)
require.NotNil(t, rateLimiter)
require.NoError(t, err)
}
func TestNewRateLimiterFailure(t *testing.T) {
invalidSettings := genRateLimitSettings(false, false, "")
invalidSettings.MaxBurst = model.NewInt(-100)
rateLimiter, err := NewRateLimiter(invalidSettings)
require.Nil(t, rateLimiter)
require.Error(t, err)
}
func TestGenerateKey(t *testing.T) {
cases := []struct {
useAuth bool
useIP bool
header string
authTokenResult string
ipResult string
headerResult string
expectedKey string
}{
{false, false, "", "", "", "", ""},
{true, false, "", "resultkey", "notme", "notme", "resultkey"},
{false, true, "", "notme", "resultkey", "notme", "resultkey"},
{false, false, "myheader", "notme", "notme", "resultkey", "resultkey"},
{true, true, "", "resultkey", "ipaddr", "notme", "resultkey"},
{true, true, "", "", "ipaddr", "notme", "ipaddr"},
{true, true, "myheader", "resultkey", "ipaddr", "hadd", "resultkeyhadd"},
{true, true, "myheader", "", "ipaddr", "hadd", "ipaddrhadd"},
}
for testnum, tc := range cases {
req := httptest.NewRequest("GET", "/", nil)
if tc.authTokenResult != "" {
req.AddCookie(&http.Cookie{
Name: model.SESSION_COOKIE_TOKEN,
Value: tc.authTokenResult,
})
}
req.RemoteAddr = tc.ipResult + ":80"
if tc.headerResult != "" {
req.Header.Set(tc.header, tc.headerResult)
}
rateLimiter, _ := NewRateLimiter(genRateLimitSettings(tc.useAuth, tc.useIP, tc.header))
key := rateLimiter.GenerateKey(req)
require.Equal(t, tc.expectedKey, key, "Wrong key on test "+strconv.Itoa(testnum))
}
}

Просмотреть файл

@@ -10,15 +10,14 @@ import (
"io/ioutil"
"net"
"net/http"
"os"
"strings"
"time"
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/rsc/letsencrypt"
"gopkg.in/throttled/throttled.v2"
"gopkg.in/throttled/throttled.v2/store/memstore"
"golang.org/x/crypto/acme/autocert"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/store"
@@ -31,6 +30,7 @@ type Server struct {
Router *mux.Router
Server *http.Server
ListenAddr *net.TCPAddr
RateLimiter *RateLimiter
didFinishListen chan struct{}
}
@@ -83,10 +83,26 @@ func (cw *CorsWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
const TIME_TO_WAIT_FOR_CONNECTIONS_TO_CLOSE_ON_SERVER_SHUTDOWN = time.Second
type VaryBy struct{}
type VaryBy struct {
useIP bool
useAuth bool
}
func (m *VaryBy) Key(r *http.Request) string {
return utils.GetIpAddress(r)
key := ""
if m.useAuth {
token, tokenLocation := ParseAuthTokenFromRequest(r)
if tokenLocation != TokenLocationNotFound {
key += token
} else if m.useIP { // If we don't find an authentication token and IP based is enabled, fall back to IP
key += utils.GetIpAddress(r)
}
} else if m.useIP { // Only if Auth based is not enabed do we use a plain IP based
key = utils.GetIpAddress(r)
}
return key
}
func redirectHTTPToHTTPS(w http.ResponseWriter, r *http.Request) {
@@ -108,33 +124,14 @@ func (a *App) StartServer() {
if *a.Config().RateLimitSettings.Enable {
l4g.Info(utils.T("api.server.start_server.rate.info"))
store, err := memstore.New(*a.Config().RateLimitSettings.MemoryStoreSize)
rateLimiter, err := NewRateLimiter(&a.Config().RateLimitSettings)
if err != nil {
l4g.Critical(utils.T("api.server.start_server.rate_limiting_memory_store"))
l4g.Critical(err.Error())
return
}
quota := throttled.RateQuota{
MaxRate: throttled.PerSec(*a.Config().RateLimitSettings.PerSec),
MaxBurst: *a.Config().RateLimitSettings.MaxBurst,
}
rateLimiter, err := throttled.NewGCRARateLimiter(store, quota)
if err != nil {
l4g.Critical(utils.T("api.server.start_server.rate_limiting_rate_limiter"))
return
}
httpRateLimiter := throttled.HTTPRateLimiter{
RateLimiter: rateLimiter,
VaryBy: &VaryBy{},
DeniedHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
l4g.Error("%v: Denied due to throttling settings code=429 ip=%v", r.URL.Path, utils.GetIpAddress(r))
throttled.DefaultDeniedHandler.ServeHTTP(w, r)
}),
}
handler = httpRateLimiter.RateLimit(handler)
a.Srv.RateLimiter = rateLimiter
handler = rateLimiter.RateLimitHandler(handler)
}
a.Srv.Server = &http.Server{
@@ -161,18 +158,34 @@ func (a *App) StartServer() {
l4g.Info(utils.T("api.server.start_server.listening.info"), listener.Addr().String())
if *a.Config().ServiceSettings.Forward80To443 {
go func() {
redirectListener, err := net.Listen("tcp", ":80")
if err != nil {
listener.Close()
l4g.Error("Unable to setup forwarding: " + err.Error())
return
}
defer redirectListener.Close()
// Migration from old let's encrypt library
if *a.Config().ServiceSettings.UseLetsEncrypt {
if stat, err := os.Stat(*a.Config().ServiceSettings.LetsEncryptCertificateCacheFile); err == nil && !stat.IsDir() {
os.Remove(*a.Config().ServiceSettings.LetsEncryptCertificateCacheFile)
}
}
http.Serve(redirectListener, http.HandlerFunc(redirectHTTPToHTTPS))
}()
m := &autocert.Manager{
Cache: autocert.DirCache(*a.Config().ServiceSettings.LetsEncryptCertificateCacheFile),
Prompt: autocert.AcceptTOS,
}
if *a.Config().ServiceSettings.Forward80To443 {
if *a.Config().ServiceSettings.UseLetsEncrypt {
go http.ListenAndServe(":http", m.HTTPHandler(nil))
} else {
go func() {
redirectListener, err := net.Listen("tcp", ":80")
if err != nil {
listener.Close()
l4g.Error("Unable to setup forwarding: " + err.Error())
return
}
defer redirectListener.Close()
http.Serve(redirectListener, http.HandlerFunc(redirectHTTPToHTTPS))
}()
}
}
a.Srv.didFinishListen = make(chan struct{})
@@ -180,8 +193,6 @@ func (a *App) StartServer() {
var err error
if *a.Config().ServiceSettings.ConnectionSecurity == model.CONN_SECURITY_TLS {
if *a.Config().ServiceSettings.UseLetsEncrypt {
var m letsencrypt.Manager
m.CacheFile(*a.Config().ServiceSettings.LetsEncryptCertificateCacheFile)
tlsConfig := &tls.Config{
GetCertificate: m.GetCertificate,

Просмотреть файл

@@ -104,7 +104,7 @@ func (a *App) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) {
return nil, result.Err
}
a.sendUpdatedTeamEvent(oldTeam)
a.sendTeamEvent(oldTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM)
return oldTeam, nil
}
@@ -122,17 +122,17 @@ func (a *App) PatchTeam(teamId string, patch *model.TeamPatch) (*model.Team, *mo
return nil, err
}
a.sendUpdatedTeamEvent(updatedTeam)
a.sendTeamEvent(updatedTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM)
return updatedTeam, nil
}
func (a *App) sendUpdatedTeamEvent(team *model.Team) {
func (a *App) sendTeamEvent(team *model.Team, event string) {
sanitizedTeam := &model.Team{}
*sanitizedTeam = *team
sanitizedTeam.Sanitize()
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_UPDATE_TEAM, "", "", "", nil)
message := model.NewWebSocketEvent(event, "", "", "", nil)
message.Add("team", sanitizedTeam.ToJson())
a.Go(func() {
a.Publish(message)
@@ -685,7 +685,7 @@ func (a *App) postRemoveFromTeamMessage(user *model.User, channel *model.Channel
Type: model.POST_REMOVE_FROM_TEAM,
UserId: user.Id,
Props: model.StringInterface{
"removedUsername": user.Username,
"username": user.Username,
},
}
@@ -824,6 +824,8 @@ func (a *App) PermanentDeleteTeam(team *model.Team) *model.AppError {
return result.Err
}
a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM)
return nil
}
@@ -838,6 +840,8 @@ func (a *App) SoftDeleteTeam(teamId string) *model.AppError {
return result.Err
}
a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM)
return nil
}

Просмотреть файл

@@ -21,6 +21,9 @@ import (
_ "github.com/go-ldap/ldap"
_ "github.com/hashicorp/memberlist"
_ "github.com/mattermost/rsc/qr"
_ "github.com/prometheus/client_golang/prometheus"
_ "github.com/prometheus/client_golang/prometheus/promhttp"
_ "github.com/tylerb/graceful"
_ "gopkg.in/olivere/elastic.v5"
)

Просмотреть файл

@@ -346,22 +346,22 @@ func createUser(idx int, teamMemberships int, channelMemberships int, teamsAndCh
}
useMilitaryTime := "false"
if rand.Intn(2) == 0 {
if idx != 0 && rand.Intn(2) == 0 {
useMilitaryTime = "true"
}
collapsePreviews := "false"
if rand.Intn(2) == 0 {
if idx != 0 && rand.Intn(2) == 0 {
collapsePreviews = "true"
}
messageDisplay := "clean"
if rand.Intn(2) == 0 {
if idx != 0 && rand.Intn(2) == 0 {
messageDisplay = "compact"
}
channelDisplayMode := "full"
if rand.Intn(2) == 0 {
if idx != 0 && rand.Intn(2) == 0 {
channelDisplayMode = "centered"
}

Просмотреть файл

@@ -28,9 +28,10 @@ const (
var MaxNotificationsPerChannelDefault int64 = 1000000
var serverCmd = &cobra.Command{
Use: "server",
Short: "Run the Mattermost server",
RunE: runServerCmd,
Use: "server",
Short: "Run the Mattermost server",
RunE: runServerCmd,
SilenceUsage: true,
}
func runServerCmd(cmd *cobra.Command, args []string) error {
@@ -41,11 +42,10 @@ func runServerCmd(cmd *cobra.Command, args []string) error {
disableConfigWatch, _ := cmd.Flags().GetBool("disableconfigwatch")
runServer(config, disableConfigWatch)
return nil
return runServer(config, disableConfigWatch)
}
func runServer(configFileLocation string, disableConfigWatch bool) {
func runServer(configFileLocation string, disableConfigWatch bool) error {
options := []app.Option{app.ConfigFile(configFileLocation)}
if disableConfigWatch {
options = append(options, app.DisableConfigWatch)
@@ -54,7 +54,7 @@ func runServer(configFileLocation string, disableConfigWatch bool) {
a, err := app.New(options...)
if err != nil {
l4g.Error(err.Error())
return
return err
}
defer a.Shutdown()
@@ -174,6 +174,8 @@ func runServer(configFileLocation string, disableConfigWatch bool) {
a.Jobs.StopSchedulers()
a.Jobs.StopWorkers()
return nil
}
func runSecurityJob(a *app.App) {

Просмотреть файл

@@ -59,6 +59,7 @@
"ExperimentalEnableDefaultChannelLeaveJoinMessages": true,
"ExperimentalGroupUnreadChannels": false,
"ImageProxyType": "",
"ImageProxyOptions": "",
"ImageProxyURL": ""
},
"TeamSettings": {
@@ -180,6 +181,7 @@
"MaxBurst": 100,
"MemoryStoreSize": 10000,
"VaryByRemoteAddr": true,
"VaryByUser": false,
"VaryByHeader": ""
},
"PrivacySettings": {

113
glide.lock сгенерированный
Просмотреть файл

@@ -1,23 +1,19 @@
hash: fa27dd8f4fd1b15c505a3d6f2023662471391e4a3ea22e67c829376c7e6e90c8
updated: 2018-01-05T10:08:00.418197689+01:00
hash: 5e8ab6acb5c3bb7dbedfc6e837cc529e72affea22384ec59e82f0e3c13379b6f
updated: 2018-01-25T15:20:13.899302483-08:00
imports:
- name: github.com/alecthomas/log4go
version: 3fbce08846379ec7f4f6bc7fce6dd01ce28fae4c
repo: https://github.com/mattermost/log4go.git
- name: github.com/armon/go-metrics
version: 7aa49fde808223f8dadfdbfd3a20ff6c19e5f9ec
- name: github.com/avct/uasurfer
version: 7b6f7205267b5b81d20da3f09ec3dea3b3d90cf8
- name: github.com/beorn7/perks
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
subpackages:
- quantile
- name: github.com/corpix/uarand
version: 2b8494104d86337cdd41d0a49cbed8e4583c0ab4
- name: github.com/cpanato/html2text
version: d47a5532a7bc36ad7b2b8ec3eebe24e975154f94
- name: github.com/davecgh/go-spew
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
version: ecdeabc65495df2dec95d7c4a4c3e021903035e5
subpackages:
- spew
- name: github.com/dgryski/dgoogauth
@@ -25,19 +21,19 @@ imports:
- name: github.com/dimchansky/utfbom
version: 6c6132ff69f0f6c088739067407b5d32c52e1d0f
- name: github.com/disintegration/imaging
version: dd50a3ee9985ccd313a2f03c398fcaedc96dc707
version: 1884593a19ddc6f2ea050403430d02c1d0fc1283
- name: github.com/dyatlov/go-opengraph
version: 41a3523719dfbe7e8f853fbd4061867543db5270
subpackages:
- opengraph
- name: github.com/fsnotify/fsnotify
version: 629574ca2a5df945712d3079857300b5e4da0236
version: c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9
- name: github.com/go-ini/ini
version: 32e4c1e6bc4e7d0d8451aa6b75200d19e37a536a
- name: github.com/go-ldap/ldap
version: 8168ee085ee43257585e50c6441aadf54ecb2c9f
version: bb7a9ca6e4fbc2129e3db588a34bc970ffe811a9
- name: github.com/go-redis/redis
version: d0f86971b5d61de9cebd2616b932acb7ba14d957
version: 4021ace05686f632ff17fd824bbed229fc474cf8
subpackages:
- internal
- internal/consistenthash
@@ -45,14 +41,14 @@ imports:
- internal/pool
- internal/proto
- name: github.com/go-sql-driver/mysql
version: a0583e0143b1624142adab07e0e97fe106d99561
version: bc14601d1bd56421dd60f561e6052c9ed77f9daf
- name: github.com/golang/freetype
version: e2365dfdc4a05e4b8299a783240d4a7d5a65d4e4
subpackages:
- raster
- truetype
- name: github.com/golang/protobuf
version: 1e59b77b52bf8e4b449a57e6f79f21226d571845
version: 925541529c1fa6821df4e44ce2723319eb2be768
subpackages:
- proto
- name: github.com/gorilla/context
@@ -60,13 +56,13 @@ imports:
- name: github.com/gorilla/handlers
version: 90663712d74cb411cbef281bc1e08c19d1a76145
- name: github.com/gorilla/mux
version: 7f08801859139f86dfafd1c296e2cba9a80d292e
version: 53c1911da2b537f792e7cafcb446b05ffe33b996
- name: github.com/gorilla/websocket
version: ea4d1f681babbce9545c9c5f3d5194a789c89f5b
version: 91f589db023d66e4aba7112d44cc0d2fb091c553
- name: github.com/hashicorp/errwrap
version: 7554cd9344cec97297fa6649b055a8c98c2a1e55
- name: github.com/hashicorp/go-immutable-radix
version: 8aac2701530899b64bdea735a1de8da899815220
version: 59b67882ec612f43b9d4c4fd97cebd507be4b3ee
- name: github.com/hashicorp/go-msgpack
version: fa3f63826f7c23912c15263591e65d54d080b458
subpackages:
@@ -92,23 +88,25 @@ imports:
- json/scanner
- json/token
- name: github.com/hashicorp/memberlist
<<<<<<< HEAD
version: caa5d20d6a642b7543b3745e54031a96008bee57
- name: github.com/icrowley/fake
version: e64cc2cf92049a299f359734c6ea76073f2a8b2c
=======
version: 3d8438da9589e7b608a83ffac1ef8211486bcb7c
>>>>>>> Updated dependencies and added avct/uasurfer
- name: github.com/icrowley/fake
version: 4178557ae428460c3780a381c824a1f3aceb6325
- name: github.com/inconshreveable/mousetrap
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
- name: github.com/jehiah/go-strftime
version: 834e15c05a45371503440cc195bbd05c9a0968d9
- name: github.com/lib/pq
version: 83612a56d3dd153a94a629cd64925371c9adad78
version: 19c8e9ad00952ce0c64489b60e8df88bb16dd514
subpackages:
- oid
- name: github.com/magiconair/properties
version: 49d762b9817ba1c2e9d0c69183c2b4a8b8f1d934
- name: github.com/mailru/easyjson
version: 32fa128f234d041f196a9f3e0fea5ac9772c08e1
subpackages:
- buffer
- jlexer
- jwriter
- name: github.com/mattermost/gorp
version: 995ddf2264c4ad45fbaf342f7500e4787ebae84a
- name: github.com/mattermost/html2text
@@ -120,15 +118,13 @@ imports:
- qr
- qr/coding
- name: github.com/matttproud/golang_protobuf_extensions
version: 3247c84500bff8d9fb6d579d800f20b3e091582c
version: c12348ce28de40eed0136aa2b644d0ee0650e56c
subpackages:
- pbutil
- name: github.com/miekg/dns
version: f5ac34d755eb6975958108413c7802a782ca16c8
- name: github.com/minio/go-homedir
version: 4d76aabb80b22bad8695d3904e943f1fb5e6199f
version: 5364553f1ee9cddc7ac8b62dce148309c386695b
- name: github.com/minio/minio-go
version: 4e0f567303d4cc90ceb055a451959fb9fc391fb9
version: 14f1d472d115bac5ca4804094aa87484a72ced61
subpackages:
- pkg/credentials
- pkg/encrypt
@@ -136,8 +132,10 @@ imports:
- pkg/s3signer
- pkg/s3utils
- pkg/set
- name: github.com/mitchellh/go-homedir
version: b8bc1bf767474819792c23f32d8286a45736f1c6
- name: github.com/mitchellh/mapstructure
version: 06020f85339e21b2478f756a78e295255ffa4d6a
version: b4575eea38cca1123ec2dc90c26529b5c5acfcff
- name: github.com/mssola/user_agent
version: 5243daae23628aeae9b6268541406bd5e95d5964
- name: github.com/nicksnyder/go-i18n
@@ -148,21 +146,27 @@ imports:
- i18n/language
- i18n/translation
- name: github.com/NYTimes/gziphandler
version: 47ca22a0aeea4c9ceddfb935d818d636d934c312
version: 289a3b81f5aedc99f8d6eb0f67827c142f1310d8
- name: github.com/olivere/elastic
version: c51e74f9bcab8906a2f6cf5660dac396ba51b3d6
subpackages:
- config
- uritemplates
- name: github.com/pborman/uuid
version: e790cca94e6cc75c7064b1332e63811d4aae1a53
- name: github.com/pelletier/go-toml
version: 0131db6d737cfbbfb678f8b7d92e55e27ce46224
version: acdc4509485b587f5e675510c4f2c63e90ff68a8
- name: github.com/pkg/errors
version: e881fd58d78e04cf6d0de1217f8707c8cc2249bc
version: 645ef00459ed84a119197bfb8d8205042c6df63d
- name: github.com/pmezard/go-difflib
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
version: 792786c7400a136282c1664665ae0a8db921c6c2
subpackages:
- difflib
- name: github.com/prometheus/client_golang
version: c5b7fccd204277076155f10851dad72b76a49317
version: 06bc6e01f4baf4ee783ffcd23abfcb0b0f9dfada
subpackages:
- prometheus
- prometheus/promhttp
- name: github.com/prometheus/client_model
version: 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c
subpackages:
@@ -171,8 +175,14 @@ imports:
version: 89604d197083d4781071d3c65855d24ecfb0a563
subpackages:
- expfmt
- internal/bitbucket.org/ww/goautoneg
- model
- name: github.com/prometheus/procfs
version: b15cd069a83443be3154b719d0cc9fe8117f09fb
version: cb4147076ac75738c9a7d279075a253c0cc5acbd
subpackages:
- internal/util
- nfs
- xfs
- name: github.com/rsc/letsencrypt
version: 33926faef6d434b854ea994228f11d0185faa0c1
- name: github.com/rwcarlsen/goexif
@@ -187,38 +197,38 @@ imports:
- name: github.com/segmentio/backo-go
version: 204274ad699c0983a70203a566887f17a717fef4
- name: github.com/spf13/afero
version: 57afd63c68602b63ed976de00dd066ccb3c319db
version: bb8f1927f2a9d3ab41c9340aa034f6b803f4359c
subpackages:
- mem
- name: github.com/spf13/cast
version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
- name: github.com/spf13/cobra
version: b95ab734e27d33e0d8fbabf71ca990568d4e2020
version: f91529fc609202eededff4de2dc0ba2f662240a3
- name: github.com/spf13/jwalterweatherman
version: 7c0cea34c8ece3fbeb2b27ab9b59511d360fb394
- name: github.com/spf13/pflag
version: e57e3eeb33f795204c1ca35f56c44f83227c6e66
version: 4c012f6dcd9546820e378d0bdda4d8fc772cdfea
- name: github.com/spf13/viper
version: aafc9e6bc7b7bb53ddaa75a5ef49a17d6e654be5
- name: github.com/stretchr/objx
version: cbeaeb16a013161a98496fad62933b1d21786672
version: 477a77ecc69700c7cdeb1fa9e129548e1c1c393c
- name: github.com/stretchr/testify
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
version: b91bfb9ebec76498946beb6af7c0230c7cc7ba6c
subpackages:
- assert
- mock
- require
- suite
- name: github.com/tylerb/graceful
version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb
version: d72b0151351a13d0421b763b88f791469c4f5dc7
- name: github.com/xenolf/lego
version: b929aa5aab5ad2e197bb3d74ef99fac61bfa47bc
version: 6bddbfd17a6e1ab782617eeab2f2007c6550b160
subpackages:
- acme
- name: github.com/xtgo/uuid
version: a0b114877d4caeffbd7f87e3757c17fce570fea7
- name: golang.org/x/crypto
version: b3c9a1d25cfbbbab0ff4780b71c4f54e6e92a0de
version: 3d37316aaa6bd9929127ac9a527abf408178ea7b
subpackages:
- bcrypt
- blowfish
@@ -234,29 +244,37 @@ imports:
- tiff
- tiff/lzw
- name: golang.org/x/net
version: 434ec0c7fe3742c984919a691b2018a6e9694425
version: 0ed95abb35c445290478a5348a7b38bb154135fd
subpackages:
- bpf
- context
- html
- html/atom
- idna
- internal/iana
- internal/socket
- ipv4
- ipv6
- lex/httplex
- name: golang.org/x/sys
version: 810d7000345868fc619eb81f46307107118f4ae1
version: 03467258950d845cd1877eab69461b98e8c09219
subpackages:
- unix
- name: golang.org/x/text
version: e19ae1496984b1c655b8044a65c0300a3c878dd3
subpackages:
- secure/bidirule
- transform
- unicode/bidi
- unicode/norm
- name: golang.org/x/time
version: 6dc17368e09b0e8634d71cac8168d853e869a0c7
subpackages:
- rate
- name: google.golang.org/appengine
version: 5bee14b453b4c71be47ec1781b0fa61c2ea182db
subpackages:
- cloudsql
- name: gopkg.in/alexcesaro/quotedprintable.v3
version: 2caba252f4dc53eaf6b553000885530023f54623
- name: gopkg.in/asn1-ber.v1
@@ -264,10 +282,7 @@ imports:
- name: gopkg.in/gomail.v2
version: 41f3572897373c5538c50a2402db15db079fa4fd
- name: gopkg.in/olivere/elastic.v5
version: 171ce647da4acfb30ffc99981d66d80bdea6bcee
subpackages:
- config
- uritemplates
version: c51e74f9bcab8906a2f6cf5660dac396ba51b3d6
- name: gopkg.in/square/go-jose.v1
version: aa2e30fdd1fe9dd3394119af66451ae790d50e0d
subpackages:

Просмотреть файл

@@ -5,29 +5,35 @@ import:
repo: https://github.com/mattermost/log4go.git
- package: github.com/dgryski/dgoogauth
- package: github.com/disintegration/imaging
version: v1.2.4
version: v1.3.0
- package: github.com/dyatlov/go-opengraph
subpackages:
- opengraph
- package: github.com/fsnotify/fsnotify
version: v1.4.2
version: v1.4.7
- package: github.com/go-ldap/ldap
version: v2.5.0
version: v2.5.1
- package: github.com/go-redis/redis
version: v6.8.2
- package: github.com/go-sql-driver/mysql
version: v1.3
- package: github.com/golang/freetype
- package: github.com/gorilla/handlers
version: v1.3.0
- package: github.com/gorilla/mux
version: v1.6.0
version: v1.6.1
- package: github.com/gorilla/websocket
version: v1.2.0
- package: github.com/hashicorp/memberlist
- package: github.com/icrowley/fake
- package: github.com/lib/pq
- package: github.com/mattermost/gorp
- package: github.com/mattermost/html2text
- package: github.com/mattermost/rsc
subpackages:
- qr
- package: github.com/minio/minio-go
version: v3.0.3
version: 4.0.6
subpackages:
- pkg/credentials
- package: github.com/mssola/user_agent
- package: github.com/nicksnyder/go-i18n
version: v1.10.0
@@ -35,6 +41,8 @@ import:
- i18n
- package: github.com/pborman/uuid
version: v1.1
- package: github.com/pkg/errors
version: v0.8.0
- package: github.com/rsc/letsencrypt
version: v0.0.1
- package: github.com/rwcarlsen/goexif
@@ -43,56 +51,31 @@ import:
- package: github.com/segmentio/analytics-go
version: 2.1.1
- package: github.com/spf13/cobra
- package: github.com/spf13/pflag
version: v1.0.0
- package: github.com/spf13/viper
- package: github.com/tylerb/graceful
version: v1.2.15
- package: github.com/stretchr/testify
version: v1.2.0
subpackages:
- assert
- mock
- require
- package: golang.org/x/crypto
subpackages:
- bcrypt
- package: golang.org/x/image
subpackages:
- bmp
- package: golang.org/x/net
subpackages:
- bpf
- package: golang.org/x/sys
subpackages:
- unix
- package: gopkg.in/gomail.v2
version: 2.0.0
- package: gopkg.in/olivere/elastic.v5
version: v6.1.4
- package: gopkg.in/throttled/throttled.v2
version: v2.1.0
subpackages:
- store/memstore
- package: github.com/prometheus/client_golang
version: v0.8.0
subpackages:
- prometheus
- package: github.com/beorn7/perks
subpackages:
- quantile
- package: github.com/golang/protobuf
subpackages:
- proto
- package: github.com/prometheus/client_model
subpackages:
- go
- package: github.com/prometheus/common
subpackages:
- expfmt
- package: github.com/matttproud/golang_protobuf_extensions
version: v1.0.0
subpackages:
- pbutil
- package: github.com/prometheus/procfs
- package: github.com/cpanato/html2text
- package: gopkg.in/olivere/elastic.v5
version: v5.0.53
- package: github.com/mattermost/gorp
version: 995ddf2264c4ad45fbaf342f7500e4787ebae84a
- package: github.com/go-redis/redis
version: v6.7.3
- package: github.com/stretchr/testify
version: v1.1.4
subpackages:
- assert
- require
- package: gopkg.in/gomail.v2
version: 2.0.0
- package: github.com/mattermost/html2text
- package: github.com/icrowley/fake
- package: github.com/avct/uasurfer
- package: gopkg.in/yaml.v2

Просмотреть файл

@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "Verwaltung und Erstellung von öffentlichen Kanälen ist auf Team- und Systemadministratoren begrenzt."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "Dieser Kanal wurde in einen öffentlichen Kanal umgewandelt und kann von jedem Teammitglied betreten werden."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "Dieser Kanal wurde in einen privaten Kanal umgewandelt."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "Für die Erstellung eines Direktnachrichtenkanals muss der createDirectChannel-API-Service verwendet werden"
@@ -3352,7 +3360,7 @@
},
{
"id": "app.import.validate_post_import_data.create_at_zero.error",
"translation": "Post-Eigenschaft CreateAt darf nicht Null sein, wenn angegeben."
"translation": "Nachrichteigenschaft CreateAt darf nicht Null sein."
},
{
"id": "app.import.validate_post_import_data.message_length.error",
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "Fehlende erforderliche Nachrichteigenschaft: User."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "Reaktionseigenschaft CreateAt muss größer als CreateAt der übergeordneten Nachricht sein."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "Fehlende erforderliche Reaktionseigenschaft: create_at."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "Reaktionseigenschaft CreateAt darf nicht Null sein."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "EmojiName-Eigenschaft der Reaktion ist länger als die maximal erlaubte Länge."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "Fehlende erforderliche Reaktionseigenschaft: EmojiName."
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "Fehlende erforderliche Reaktionseigenschaft: User."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "Antworteigenschaft CreateAt muss größer als CreateAt der übergeordneten Nachricht sein."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "Fehlende erforderliche Antworteigenschaft: create_at."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "Antworteigenschaft CreateAt darf nicht Null sein."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "Message-Eigenschaft der Antwort ist länger als die maximal erlaubte Länge."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "Fehlende erforderliche Antworteigenschaft: Message."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "Fehlende erforderliche Antworteigenschaft: User."
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "Team allowed_domains ist zu lang."
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "Benutzer Position ist zu lang."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Ungültiges Profilbild."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "Benutzer roles sind nicht gültig."
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "Bis muss größer als von sein"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Invalid atmos/camo image proxy options for service settings. Must be set to your shared key."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "E-Mail-Stapelverarbeitung lässt sich bei aktiviertem Clustering nicht aktivieren."
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "Ungültige Thumbnauilbreite in Dateieinstellungen. Muss eine positive Zahl sein."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Ungültiger Bild-Proxy-Typ für Diensteinstellungen."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "AD/LDAP-Feld \"BaseDN\" ist erforderlich."
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "Das persönliche Zugriffs-Token konnte nicht abgerufen werden"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "Es konnten nicht alle persönlichen Zugriffs-Token abgerufen werden"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "Das persönliche Zugriffs-Token konnte nicht über Token abgerufen werden"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "Das persönliche Zugriffs-Token konnte nicht gespeichert werden"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "Beim Suchen von Zugangs-Tokens wurde ein Fehler festgestellt"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "Die Anzahl der eingehenden Webhooks konnte nicht gezählt werden"

Просмотреть файл

@@ -153,7 +153,7 @@
},
{
"id": "api.channel.add_member.added",
"translation": "%v added to the channel by %v"
"translation": "%v added to the channel by %v."
},
{
"id": "api.channel.add_member.find_channel.app_error",
@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "Public Channel management and creation is restricted to Team and System Administrators."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "This channel has been converted to a Public Channel and can be joined by any team member."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "This channel has been converted to a Private Channel."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "Must use createDirectChannel API service for direct message channel creation"
@@ -233,7 +241,7 @@
},
{
"id": "api.channel.delete_channel.archived",
"translation": "%v has archived the channel."
"translation": "%v archived the channel."
},
{
"id": "api.channel.delete_channel.cannot.app_error",
@@ -297,7 +305,7 @@
},
{
"id": "api.channel.join_channel.post_and_forget",
"translation": "%v has joined the channel."
"translation": "%v joined the channel."
},
{
"id": "api.channel.leave.default.app_error",
@@ -313,15 +321,7 @@
},
{
"id": "api.channel.leave.left",
"translation": "%v has left the channel."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "This channel has been converted to a Public Channel and can be joined by any team member."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "This channel has been converted to a Private Channel."
"translation": "%v left the channel."
},
{
"id": "api.channel.post_update_channel_displayname_message_and_forget.create_post.error",
@@ -369,7 +369,7 @@
},
{
"id": "api.channel.remove_member.removed",
"translation": "%v was removed from the channel."
"translation": "%v removed from the channel."
},
{
"id": "api.channel.remove_member.unable.app_error",
@@ -2184,7 +2184,7 @@
},
{
"id": "api.team.add_user_to_team.added",
"translation": "%v added to the team by %v"
"translation": "%v added to the team by %v."
},
{
"id": "api.team.add_user_to_team.missing_parameter.app_error",
@@ -2320,7 +2320,7 @@
},
{
"id": "api.team.remove_user_from_team.removed",
"translation": "%v was removed from the team."
"translation": "%v removed from the team."
},
{
"id": "api.team.signup_team.email_disabled.app_error",
@@ -3358,54 +3358,6 @@
"id": "app.import.validate_direct_post_import_data.user_missing.error",
"translation": "Missing required direct post property: user"
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "Missing required Reaction property: User."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "Missing required Reaction property: EmojiName."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "Reaction EmojiName property is longer than the maximum permitted length."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "Missing required Reaction property: create_at."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "Reaction CreateAt property must not be zero."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "Reaction CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "Missing required Reply property: User."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "Missing required Reply property: Message."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "Reply Message property is longer than the maximum permitted length."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "Missing required Reply property: create_at."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "Reply CreateAt property must not be zero."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "Reply CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_post_import_data.channel_missing.error",
"translation": "Missing required Post property: Channel."
@@ -3434,6 +3386,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "Missing required Post property: User."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "Reaction CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "Missing required Reaction property: create_at."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "Reaction CreateAt property must not be zero."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "Reaction EmojiName property is longer than the maximum permitted length."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "Missing required Reaction property: EmojiName."
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "Missing required Reaction property: User."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "Reply CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "Missing required Reply property: create_at."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "Reply CreateAt property must not be zero."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "Reply Message property is longer than the maximum permitted length."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "Missing required Reply property: Message."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "Missing required Reply property: User."
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "Team allowed_domains is too long."
@@ -3570,6 +3570,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "User Position is too long."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Invalid profile image."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "User roles are not valid."
@@ -3582,10 +3586,6 @@
"id": "app.import.validate_user_import_data.username_missing.error",
"translation": "Missing require user property: username."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Invalid profile image."
},
{
"id": "app.import.validate_user_teams_import_data.invalid_roles.error",
"translation": "Invalid roles for User's Team Membership."
@@ -4650,6 +4650,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "To must be greater than From"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Invalid atmos/camo image proxy options for service settings. Must be set to your shared key."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "Unable to enable email batching when clustering is enabled."
@@ -4762,6 +4766,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "Invalid thumbnail width for file settings. Must be a positive number."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Invalid image proxy type for service settings."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "AD/LDAP field \"BaseDN\" is required."
@@ -4822,14 +4830,6 @@
"id": "model.config.is_valid.listen_address.app_error",
"translation": "Invalid listen address for service settings Must be set."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Invalid image proxy type for service settings."
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Invalid atmos/camo image proxy options for service settings. Must be set to your shared key."
},
{
"id": "model.config.is_valid.localization.available_locales.app_error",
"translation": "Available Languages must contain Default Client Language"
@@ -6874,26 +6874,26 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "We couldn't get the personal access token"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "We couldn't get the personal access token by token"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "We couldn't get all personal access tokens"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "We couldn't get the personal access token by token"
},
{
"id": "store.sql_user_access_token.get_by_user.app_error",
"translation": "We couldn't get the personal access tokens by user"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "We encountered an error searching user access tokens"
},
{
"id": "store.sql_user_access_token.save.app_error",
"translation": "We couldn't save the personal access token"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "We encountered an error searching user access tokens"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "We couldn't count the incoming webhooks"

Просмотреть файл

@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "La gestión y creación de Canales Públicos está restringida a los Administradores de Equipo y Sistema."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "Este canal ha sido convertido a un Canal Público y cualquier miembro del equipo puede unirse."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "Este canal ha sido convertido a un Canal Privado."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "Debe usar el servicio del api createDirectChannel para crear un canal de mensajes directos"
@@ -233,7 +241,7 @@
},
{
"id": "api.channel.delete_channel.archived",
"translation": "%v ha archivado el canal."
"translation": "%v archivó el canal."
},
{
"id": "api.channel.delete_channel.cannot.app_error",
@@ -297,7 +305,7 @@
},
{
"id": "api.channel.join_channel.post_and_forget",
"translation": "%v se ha unido al canal."
"translation": "%v se unió al canal."
},
{
"id": "api.channel.leave.default.app_error",
@@ -313,7 +321,7 @@
},
{
"id": "api.channel.leave.left",
"translation": "%v ha abandonado el canal."
"translation": "%v abandonó el canal."
},
{
"id": "api.channel.post_update_channel_displayname_message_and_forget.create_post.error",
@@ -361,7 +369,7 @@
},
{
"id": "api.channel.remove_member.removed",
"translation": "%v fue removido del canal."
"translation": "%v removido del canal."
},
{
"id": "api.channel.remove_member.unable.app_error",
@@ -2312,7 +2320,7 @@
},
{
"id": "api.team.remove_user_from_team.removed",
"translation": "%v fue removido del equipo."
"translation": "%v removido del equipo."
},
{
"id": "api.team.signup_team.email_disabled.app_error",
@@ -3352,7 +3360,7 @@
},
{
"id": "app.import.validate_post_import_data.create_at_zero.error",
"translation": "La propiedad CreateAt del Mensaje no debe ser cero si se proporciona."
"translation": "La propiedad CreateAt del Mensaje no debe ser cero."
},
{
"id": "app.import.validate_post_import_data.message_length.error",
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "Falta la propiedad obligatoria del mensaje: User."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "La propiedad CreateAt de la Reacción debe ser mayor a la propiedad CreateAt del mensaje al que pertenece."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "Falta la propiedad de la Reacción: create_at."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "La propiedad CreateAt de la Reacción no debe ser cero."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "La propiedad EmojiName de la reacción supera la longitud máxima permitida."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "Falta la propiedad obligatoria de la Reacción: EmojiName."
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "Falta la propiedad obligatoria de la Reacción: User."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "La propiedad CreateAt debe ser mayor al CreateAt del mensaje padre."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "Falta la propiedad de la respuesta: create_at."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "La propiedad CreateAt de la respuesta no debe ser cero."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "La propiedad Message de la respuesta supera la longitud máxima permitida."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "Falta la propiedad obligatoria de la respuesta: Message."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "Falta la propiedad obligatoria de la respuesta: User."
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "La propiedad del equipo allowed_domains es demasiado larga."
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "La propiedad Position del usuario es demasiado larga."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Imagen de perfil no válida."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "Los roles del usuario no son válidos."
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "Desde debe ser mayor que Hasta"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Opción atmos/camo del proxy de imágenes no es válida en la configuración del servicio. Se debe establecer con la clave compartida."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "No se puede habilitar el correo electrónico por lotes cuando la agrupación de servidores está habilitada"
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "El ancho para la imagen de miniatura es inválido en la configuración de archivos. Debe ser un número positivo."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Tipo de proxy para las imágenes no válido en la configuración del servicio."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "El campo AD/LDAP \"BaseDN\" es obligatorio."
@@ -5336,7 +5404,7 @@
},
{
"id": "model.user.is_valid.position.app_error",
"translation": "Cargo no válido: no debe ser más de 35 caracteres."
"translation": "Cargo no válido: no debe ser más de 128 caracteres."
},
{
"id": "model.user.is_valid.pwd.app_error",
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "No pudimos obtener el token de acceso personal"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "No pudimos obtener todos los tokens de acceso personal"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "No pudimos obtener el token de acceso personal por token"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "No pudimos guardar el token de acceso personal"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "Encontramos un error buscando los tokens de acceso"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "No pudimos contar la cantidad de webhooks entrantes"

Просмотреть файл

@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "La gestion et la création de canaux publics sont réservés aux administrateurs système et administrateurs d'équipe."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "This channel has been converted to a Public Channel and can be joined by any team member."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "This channel has been converted to a Private Channel."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "Vous devez utiliser le service d'API createDirectChannel pour la création d'un canal de messages personnels"
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "La propriété requise du message est manquante : User."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "Reaction CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "La propriété requise pour un message est manquante : create_at."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "La propriété de message CreateAt ne doit pas être 0 si ce champ est défini."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "La propriété Message du message est plus longue que la longueur maximale autorisée."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "La propriété requise du message est manquante : User."
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "La propriété requise du message est manquante : User."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "Reply CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "La propriété requise pour un message est manquante : create_at."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "La propriété de message CreateAt ne doit pas être 0 si ce champ est défini."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "La propriété Message du message est plus longue que la longueur maximale autorisée."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "La propriété requise du message est manquante : Message."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "La propriété requise du message est manquante : User."
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "La propriété d'équipe allowed_domains is trop longue."
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "Le rôle de l'utilisateur est trop long."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Invalid profile image."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "Les rôles de l'utilisateur sont invalides."
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "Jusqu'à doit être supérieur à De"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Invalid atmos/camo image proxy options for service settings. Must be set to your shared key."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "Impossible d'activer l'envoi d'e-mails par lot lorsque le clustering est activé"
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "Largeur des miniatures invalide dans les paramètres de fichiers. Doit être un entier positif."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Invalid image proxy type for service settings."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "Le champ AD/LDAP \"BaseDN\" est requis."
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "Impossible de récupérer le jeton d'accès personnel"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "Impossible de récupérer le jeton d'accès personnel"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "Impossible de récupérer le jeton d'accès personnel par jeton"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "Impossible d'enregistrer le jeton d'accès personnel"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "Nous avons rencontré une erreur lors de la recherche du jeton d'accès"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "Impossible de compter les webhooks entrants"

Просмотреть файл

@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "La creazione e amministrazione di Canali Pubblici è limitata all'Amministratore di Sistema e di gruppo."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "Questo canale è stato convertito in un Canale Pubblico e ogni membro del gruppo può farne parte."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "Questo canale è stato convertito in un Canale Privato."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "Bisogna usare il servizio createDirectChannel API per la creazione dei messaggi diretti nel canale"
@@ -2176,7 +2184,7 @@
},
{
"id": "api.team.add_user_to_team.added",
"translation": "%v aggiunto al gruppo da parte di %v"
"translation": "%v aggiunto al gruppo da parte di %v."
},
{
"id": "api.team.add_user_to_team.missing_parameter.app_error",
@@ -3352,7 +3360,7 @@
},
{
"id": "app.import.validate_post_import_data.create_at_zero.error",
"translation": "L'attributo della pubblicazione CreateAt, se presente, non deve essere zero."
"translation": "La proprietà CreateAt della pubblicazione non può essere zero."
},
{
"id": "app.import.validate_post_import_data.message_length.error",
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "Proprietà della pubblicazione mancante: User."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "La proprietà della reazione CreateAt deve evvere maggiore della proprietà CreateAt della pubblicazione principale."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "Proprietà della reazione mancante: create_at."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "La proprietà della reazione CreateAt non può essere zero."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "La lunghezza della proprietà EmojiName della reazione è maggiore della lunghezza ammessa."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "Proprietà della reazione mancante: EmojiName."
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "Proprietà della reazione mancante: User."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "La proprietà CreateAt della risposta deve essere maggiore della proprietà CreateAt della pubblicazione principale."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "Proprietà della risposta mancante: create_at."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "La proprietà CreateAt della risposta non può essere zero."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "La lunghezza della proprietà Message della risposta è maggiore della lunghezza ammessa."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "Proprietà della risposta mancante: Message."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "Proprietà della risposta mancante: User."
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "Il campo allowed_domains del gruppo è troppo lungo."
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "Il campo Posizione dell'utente è troppo lungo."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Immagine profilo non valida."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "I ruoli utente non sono validi."
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "A deve essere più grand di Da"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Opzioni proxy immagine atmos/camo non valide nelle impostazione del servizio. Dev'essere una chiave condivisa."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "Impossibile abilitare la spedizione email programmata quando il supporto cluster è abilitato."
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "Larghezza antemprima non valida per le impostazioni file. Deve essere un numero positivo."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Tipo proxy immagine non valido nelle impostazioni del servizio."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "Il campo AD/LDAP \"BaseDN\" è richiesto."
@@ -5336,7 +5404,7 @@
},
{
"id": "model.user.is_valid.position.app_error",
"translation": "Posizione non valida: non deve essere maggiore di 35 caratteri."
"translation": "Posizione non valida: non deve essere maggiore di 128 caratteri."
},
{
"id": "model.user.is_valid.pwd.app_error",
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "Impossibile trovare il Token di accesso personale"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "Impossibile trovare tutti i token di accesso personale"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "Impossibile trovare il token di accesso personale per token"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "Impossibile salvare il Token di accesso personale"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "Si è verificato un errore durante la ricerca dei token di accesso personali"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "Non è stato possibile effettuare il conteggio dei webhook in ingresso"

Просмотреть файл

@@ -153,7 +153,7 @@
},
{
"id": "api.channel.add_member.added",
"translation": "%vは、%vによってチャンネルに追加されました"
"translation": "%v%v によってチャンネルに追加されました"
},
{
"id": "api.channel.add_member.find_channel.app_error",
@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "公開チャンネルの作成と管理は、チーム管理者かシステム管理者しかできません。"
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "このチャンネルは公開チャンネルに変更されたため、全てのチームメンバーが参加できるようになりました。"
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "このチャンネルは非公開チャンネルに変更されました。"
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "ダイレクトメッセージチャンネルを作成するにはcreateDirectChannel APIを使用してください"
@@ -233,7 +241,7 @@
},
{
"id": "api.channel.delete_channel.archived",
"translation": "%vがチャンネルをアーカイブしました。"
"translation": "%v がチャンネルをアーカイブしました。"
},
{
"id": "api.channel.delete_channel.cannot.app_error",
@@ -361,7 +369,7 @@
},
{
"id": "api.channel.remove_member.removed",
"translation": "%vはチャンネルから削除されました。"
"translation": "%v はチャンネルから削除されました。"
},
{
"id": "api.channel.remove_member.unable.app_error",
@@ -2312,7 +2320,7 @@
},
{
"id": "api.team.remove_user_from_team.removed",
"translation": "%v はチャンネルから削除されました。"
"translation": "%v はチームから削除されました。"
},
{
"id": "api.team.signup_team.email_disabled.app_error",
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "必須の投稿設定値 User が存在しません。"
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "リアクション作成日時の設定値は親に当たる投稿の作成日時よりも大きくなくてはなりません。"
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "必須のリアクション設定値 create_at が存在しません。"
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "リアクションの作成日時には0を設定できません。"
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "リアクション絵文字名の設定値が許可された最大長を超えています。"
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "必須のリアクション設定値 EmojiName が存在しません。"
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "必須のリアクション設定値 User が存在しません。"
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "返信作成日時の設定値は親に当たる投稿の作成日時よりも大きくなくてはなりません。"
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "必須の返信設定値 create_at が存在しません。"
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "返信の作成日時には0を設定できません。"
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "返信メッセージの設定値が許可された最大長を超えています。"
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "必須の返信設定値 Message が存在しません。"
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "必須の返信設定値 User が存在しません。"
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "チームの許可されたドメインが長すぎます。"
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "ユーザーの役職が長すぎます。"
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "不正なプロフィール画像です。"
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "ユーザーの役割が正しくありません。"
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "有効終了は有効開始の後でなくてはいけません"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "atmos/camo 画像プロキシの設定が不正です。共有キーを設定する必要があります。"
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "クラスタリングが有効化されている場合、電子メールバッチ処理は有効化できません。"
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "ファイル設定のサムネイルの幅が不正です。ゼロ以上の数を指定してください。"
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "画像プロキシタイプの設定が不正です。"
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "AD/LDAP項目 \"ベースDN\" は必須です。"
@@ -5336,7 +5404,7 @@
},
{
"id": "model.user.is_valid.position.app_error",
"translation": "不正な役職: 35文字以上にはできません"
"translation": "不正な役職: 128文字以上にはできません"
},
{
"id": "model.user.is_valid.pwd.app_error",
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "パーソナルアクセストークンを取得できませんでした"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "パーソナルアクセストークンを取得できませんでした"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "トークンによってパーソナルアクセストークンを取得することができませんでした"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "パーソナルアクセストークンを保存できませんでした。"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "アクセストークンを探す際にエラーが発生しました"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "内向きのウェブフック数を取得できませんでした"

Просмотреть файл

@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "공개 채널 생성, 관리는 팀 관리자 또는 시스템 관리자 권한이 필요합니다."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "This channel has been converted to a Public Channel and can be joined by any team member."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "This channel has been converted to a Private Channel."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "개인 메시지 채널을 만들기 위해서는 반드시 createDirectChannel API 서비스를 이용해야 함"
@@ -812,7 +820,7 @@
},
{
"id": "api.command_leave.success",
"translation": "Left the channel."
"translation": "%v 가 채널을 떠났습니다."
},
{
"id": "api.command_logout.desc",
@@ -3352,7 +3360,7 @@
},
{
"id": "app.import.validate_post_import_data.create_at_zero.error",
"translation": "Post CreateAt property must not be zero if provided."
"translation": "Post CreateAt property must not be zero."
},
{
"id": "app.import.validate_post_import_data.message_length.error",
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "Missing required Post property: User."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "Reaction CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "Missing required Reaction property: create_at."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "Reaction CreateAt property must not be zero."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "Reaction EmojiName property is longer than the maximum permitted length."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "Missing required Reaction property: EmojiName."
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "Missing required Reaction property: User."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "Reply CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "Missing required Reply property: create_at."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "Reply CreateAt property must not be zero."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "Reply Message property is longer than the maximum permitted length."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "Missing required Reply property: Message."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "Missing required Reply property: User."
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "Team allowed_domains is too long."
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "User Position is too long."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Invalid profile image."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "User roles are not valid."
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "To must be greater than From"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Invalid atmos/camo image proxy options for service settings. Must be set to your shared key."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "Unable to enable email batching when clustering is enabled"
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "파일 세팅에 대한 잘못된 썸네일 너비값입니다. 0보다 큰 값이여야 합니다."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Invalid image proxy type for service settings."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "AD/LDAP의 \"BaseDN\" 항목이 필요합니다."
@@ -5336,7 +5404,7 @@
},
{
"id": "model.user.is_valid.position.app_error",
"translation": "Invalid position: must not be longer than 35 characters."
"translation": "Invalid position: must not be longer than 128 characters."
},
{
"id": "model.user.is_valid.pwd.app_error",
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "채널을 찾을 수 없습니다"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "채널을 찾을 수 없습니다"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "채널을 찾을 수 없습니다"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "채널을 찾을 수 없습니다"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "We encountered an error finding the access token"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "Incoming webhook 갯수를 셀 수 없었습니다"

Просмотреть файл

@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "Alleen team- en systeembeheerders mogen publieke kanalen beheren en aanmaken."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "This channel has been converted to a Public Channel and can be joined by any team member."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "This channel has been converted to a Private Channel."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "U moet de 'createDirectChannel' API service gebruiken om een direct kanaal aan te maken"
@@ -812,7 +820,7 @@
},
{
"id": "api.command_leave.success",
"translation": "Left the channel."
"translation": "%v heeft het kanaal verlaten."
},
{
"id": "api.command_logout.desc",
@@ -3352,7 +3360,7 @@
},
{
"id": "app.import.validate_post_import_data.create_at_zero.error",
"translation": "Post CreateAt property must not be zero if provided."
"translation": "Post CreateAt property must not be zero."
},
{
"id": "app.import.validate_post_import_data.message_length.error",
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "Missing required Post property: User."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "Reaction CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "Missing required Reaction property: create_at."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "Reaction CreateAt property must not be zero."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "Reaction EmojiName property is longer than the maximum permitted length."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "Missing required Reaction property: EmojiName."
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "Missing required Reaction property: User."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "Reply CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "Missing required Reply property: create_at."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "Reply CreateAt property must not be zero."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "Reply Message property is longer than the maximum permitted length."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "Missing required Reply property: Message."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "Missing required Reply property: User."
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "Team allowed_domains is too long."
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "User Position is too long."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Invalid profile image."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "User roles are not valid."
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "Tot en met, moet later zijn dan Vanaf"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Invalid atmos/camo image proxy options for service settings. Must be set to your shared key."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "Niet mogelijk om bulk email aan te zetten als clustering aan staat."
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "Ongeldige voorvertonings breedte bij bestands instellingen. Moet een getal groter dan 0 zijn."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Invalid image proxy type for service settings."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "AD/LDAP veld \"BaseDN\" is verplicht."
@@ -5336,7 +5404,7 @@
},
{
"id": "model.user.is_valid.position.app_error",
"translation": "Invalid position: must not be longer than 35 characters."
"translation": "Invalid position: must not be longer than 128 characters."
},
{
"id": "model.user.is_valid.pwd.app_error",
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "Het access token kan niet verwijderd worden"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "Het access token kan niet verwijderd worden"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "Het access token kan niet verwijderd worden"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "Het access token kan niet opgeslagen worden."
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "Er is een probleem opgetreden bij het ophalen van het access token"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "Het aantal binnenkomende webhooks kan niet geteld worden"

Просмотреть файл

@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "Zarządzanie i tworzenie kanałów publicznych jest dostępne tylko dla administratorów systemu i zespołów."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "This channel has been converted to a Public Channel and can be joined by any team member."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "This channel has been converted to a Private Channel."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "Do tworzenia kanału wiadomości bezpośrednich należy użyć usługi API createDirectChannel"
@@ -637,15 +645,15 @@
},
{
"id": "api.command_dnd.desc",
"translation": "Do not disturb disables desktop and mobile push notifications."
"translation": "Tryb \"Nie przeszkadzać\" wyłącza powiadomienia desktopowe oraz mobilne powiadomienia push."
},
{
"id": "api.command_dnd.disabled",
"translation": "Do Not Disturb is disabled."
"translation": "Tryb \"Nie przeszkadzać\" jest wyłączony."
},
{
"id": "api.command_dnd.error",
"translation": "Error to retrieve the user status."
"translation": "Nie można odczytać statusu użytkownika."
},
{
"id": "api.command_dnd.name",
@@ -653,7 +661,7 @@
},
{
"id": "api.command_dnd.success",
"translation": "Do Not Disturb is enabled. You will not receive desktop or mobile push notifications until Do Not Disturb is turned off."
"translation": "Tryb \"Nie przeszkadzać\" jest włączony. Nie będziesz otrzymywać powiadomień na komputerze ani powiadomień push na urządzeniach mobilnych do czasu jego wyłączenia."
},
{
"id": "api.command_echo.create.app_error",
@@ -701,25 +709,25 @@
},
{
"id": "api.command_groupmsg.desc",
"translation": "Sends a Group Message to the specified users"
"translation": "Wysyła wiadomość grupową do wybranych użytkowników."
},
{
"id": "api.command_groupmsg.fail.app_error",
"translation": "Wystąpił błąd podczas wysyłania wiadomości do użytkownika."
"translation": "Wystąpił błąd podczas wysyłania wiadomości do użytkowników."
},
{
"id": "api.command_groupmsg.group_fail.app_error",
"translation": "Wystąpił błąd podczas tworzenia wiadomości bezpośredniej."
"translation": "Wystąpił błąd podczas tworzenia wiadomości grupowej."
},
{
"id": "api.command_groupmsg.hint",
"translation": "@[username1],@[username2] 'message'"
"translation": "@[username1],@[username2] 'wiadomość'"
},
{
"id": "api.command_groupmsg.invalid_user.app_error",
"translation": {
"one": "We couldn't find the user: {{.Users}}",
"other": "We couldn't find the users: {{.Users}}"
"one": "Nie można znaleźć użytkownika: {{.Users}}",
"other": "Nie można znaleźć użytkowników: {{.Users}}"
}
},
{
@@ -732,11 +740,11 @@
},
{
"id": "api.command_groupmsg.max_users.app_error",
"translation": "Group messages are limited to a maximum of {{.MaxUsers}} users."
"translation": "Wiadomości grupowe są ograniczone do maksymalnie {{.MaxUsers}} użytkowników."
},
{
"id": "api.command_groupmsg.min_users.app_error",
"translation": "Group messages are limited to a minimum of {{.MinUsers}} users."
"translation": "Wiadomości grupowe są ograniczone do minimum {{.MinUsers}} użytkowników."
},
{
"id": "api.command_groupmsg.missing.app_error",
@@ -748,7 +756,7 @@
},
{
"id": "api.command_groupmsg.success",
"translation": "Odbiorca wiadomości."
"translation": "Odbiorcy wiadomości."
},
{
"id": "api.command_help.desc",
@@ -900,7 +908,7 @@
},
{
"id": "api.command_remove.desc",
"translation": "Remove a member from the channel"
"translation": "Usuń członka z kanału"
},
{
"id": "api.command_remove.direct_group.app_error",
@@ -920,15 +928,15 @@
},
{
"id": "api.command_remove.name",
"translation": "remove"
"translation": "usuń"
},
{
"id": "api.command_remove.permission.app_error",
"translation": "Nie posiadasz odpowiednich uprawnień do zmiany nazwy kanału."
"translation": "Nie posiadasz odpowiednich uprawnień do usunięcia członka."
},
{
"id": "api.command_remove.user_not_in_channel",
"translation": "{{.Username}} is not a member of this channel."
"translation": "{{.Username}} nie jest członkiem tego kanału."
},
{
"id": "api.command_search.desc",
@@ -1080,7 +1088,7 @@
},
{
"id": "api.email_batching.render_batched_post.channel.app_error",
"translation": "Nie można znaleźć kanału posta dla masowych powiadomień email"
"translation": "Nie można znaleźć kanału wiadomości dla masowych powiadomień e-mail."
},
{
"id": "api.email_batching.render_batched_post.date",
@@ -1092,7 +1100,7 @@
},
{
"id": "api.email_batching.render_batched_post.go_to_post",
"translation": "Przejdź do postu"
"translation": "Do wiadomości"
},
{
"id": "api.email_batching.render_batched_post.group_message",
@@ -1104,7 +1112,7 @@
},
{
"id": "api.email_batching.render_batched_post.sender.app_error",
"translation": "Nie można znaleźć nadawcy posta dla masowych powiadomień email"
"translation": "Nie można znaleźć nadawcy wiadomości dla masowych powiadomień e-mail"
},
{
"id": "api.email_batching.send_batched_email_notification.body_text",
@@ -1334,7 +1342,7 @@
},
{
"id": "api.file.move_file.copy_within_s3.app_error",
"translation": "Unable to copy file within S3."
"translation": "Nie można skopiować pliku w S3."
},
{
"id": "api.file.move_file.delete_from_s3.app_error",
@@ -1426,7 +1434,7 @@
},
{
"id": "api.incoming_webhook.invalid_username.app_error",
"translation": "Niepoprawna nazwa uzytkownika"
"translation": "Niepoprawna nazwa użytkownika."
},
{
"id": "api.ldap.init.debug",
@@ -1634,19 +1642,19 @@
},
{
"id": "api.post.check_for_out_of_channel_mentions.link.private",
"translation": "add them to this private channel"
"translation": "dodaj ich do tego prywatnego kanału"
},
{
"id": "api.post.check_for_out_of_channel_mentions.link.public",
"translation": "add them to the channel"
"translation": "dodaj ich do kanału"
},
{
"id": "api.post.check_for_out_of_channel_mentions.message.multiple",
"translation": "@{{.Usernames}} and @{{.LastUsername}} were mentioned but they are not in the channel. Would you like to {{.Phrase}}? They will have access to all message history."
"translation": "@{{.Usernames}} oraz @{{.LastUsername}} zostali wspomnieni, ale nie było ich na kanale. Czy chcesz {{.Phrase}}? Będą mieć dostęp do całej historii wiadomości."
},
{
"id": "api.post.check_for_out_of_channel_mentions.message.one",
"translation": "@{{.Username}} was mentioned but they are not in the channel. Would you like to {{.Phrase}}? They will have access to all message history."
"translation": "@{{.Username}} został wspomniany, ale nie było go na kanale. Czy chcesz {{.Phrase}}? Będzie mieć dostęp do całej historii wiadomości."
},
{
"id": "api.post.create_post.attach_files.error",
@@ -2120,7 +2128,7 @@
},
{
"id": "api.slackimport.slack_import.team_fail",
"translation": "Nie udało się pobrać zespołu do importu.\r\n"
"translation": "Nie udało się pobrać zespołu do którego ma nastąpić import.\r\n"
},
{
"id": "api.slackimport.slack_import.zip.app_error",
@@ -2136,7 +2144,7 @@
},
{
"id": "api.slackimport.slack_sanitise_channel_properties.display_name_too_long.warn",
"translation": "Slack Importer: Kanał {{.ChannelName}} ma nagłówek, który jest za długi. Będzie on przycięty po zaimportowaniu."
"translation": "Slack Importer: Kanał {{.ChannelName}} ma wyświetlaną nazwę, która jest za długa. Będzie ona przycięta po zaimportowaniu."
},
{
"id": "api.slackimport.slack_sanitise_channel_properties.header_too_long.warn",
@@ -2144,11 +2152,11 @@
},
{
"id": "api.slackimport.slack_sanitise_channel_properties.name_too_long.warn",
"translation": "Slack Importer: Kanał {{.ChannelName}} ma nagłówek, który jest za długi. Będzie on przycięty po zaimportowaniu."
"translation": "Slack Importer: Kanał {{.ChannelName}} ma nazwę, która jest za długa. Będzie ona przycięta po zaimportowaniu."
},
{
"id": "api.slackimport.slack_sanitise_channel_properties.purpose_too_long.warn",
"translation": "Slack Importer: Kanał {{.ChannelName}} ma opis, który jest za długi. Będzie on przycięty po zaimportowaniu."
"translation": "Slack Importer: Kanał {{.ChannelName}} ma cel, który jest za długi. Będzie on przycięty po zaimportowaniu."
},
{
"id": "api.status.init.debug",
@@ -2228,7 +2236,7 @@
},
{
"id": "api.team.import_team.no_import_from.app_error",
"translation": "Nieprawidłowe zapytanie: pole rozmiaru pliku nie istnieje."
"translation": "Nieprawidłowe zapytanie: pole importFrom nie istnieje."
},
{
"id": "api.team.import_team.open.app_error",
@@ -2292,11 +2300,11 @@
},
{
"id": "api.team.join_team.post_and_forget",
"translation": "%v joined the team."
"translation": "%v dołączył do kanału."
},
{
"id": "api.team.leave.left",
"translation": "%v left the team."
"translation": "%v opuścił zespół."
},
{
"id": "api.team.permanent_delete_team.attempting.warn",
@@ -2312,7 +2320,7 @@
},
{
"id": "api.team.remove_user_from_team.removed",
"translation": "%v został usunięty z kanału."
"translation": "%v został usunięty z zespołu."
},
{
"id": "api.team.signup_team.email_disabled.app_error",
@@ -2832,7 +2840,7 @@
},
{
"id": "api.user.saml.not_available.app_error",
"translation": "Użycie SAML nie zostało skonfigurowane lub nie jest wspierane na tym serwerze."
"translation": "Użycie SAML 2.0 nie zostało skonfigurowane lub nie jest wspierane na tym serwerze."
},
{
"id": "api.user.send_email_change_email_and_forget.error",
@@ -2868,7 +2876,7 @@
},
{
"id": "api.user.send_user_access_token.error",
"translation": "Failed to send \"Personal access token added\" email successfully"
"translation": "Nie udało się wysłać maila \"Osobisty token dostępu został dodany\""
},
{
"id": "api.user.send_verify_email_and_forget.failed.error",
@@ -2880,7 +2888,7 @@
},
{
"id": "api.user.update_active.no_deactivate_sso.app_error",
"translation": "Nie możesz zmieniać stanu aktywacji kont AD/LDAP. Proszę je zmodyfikować przez serwer LDAP."
"translation": "Nie możesz zmieniać stanu aktywacji kont SSO. Proszę je zmodyfikować przez serwer SSO."
},
{
"id": "api.user.update_active.permissions.app_error",
@@ -3128,23 +3136,23 @@
},
{
"id": "app.channel.post_update_channel_purpose_message.post.error",
"translation": "Nie udało się wysłać opisu kanału"
"translation": "Nie udało się wysłać celu kanału"
},
{
"id": "app.channel.post_update_channel_purpose_message.removed",
"translation": "%s usunął opis kanału (był: %s)"
"translation": "%s usunął cel kanału (był: %s)"
},
{
"id": "app.channel.post_update_channel_purpose_message.retrieve_user.error",
"translation": "Nie udało się pobrać użytkownika podczas aktualizacji opisu kanału %v"
"translation": "Nie udało się pobrać użytkownika podczas aktualizacji celu kanału %v"
},
{
"id": "app.channel.post_update_channel_purpose_message.updated_from",
"translation": "%s zaktualizował opis kanału z: %s na: %s"
"translation": "%s zaktualizował cel kanału z: %s na: %s"
},
{
"id": "app.channel.post_update_channel_purpose_message.updated_to",
"translation": "%s zmienił opis kanału na %s"
"translation": "%s zmienił cel kanału na %s"
},
{
"id": "app.import.bulk_import.file_scan.error",
@@ -3272,7 +3280,7 @@
},
{
"id": "app.import.validate_channel_import_data.purpose_length.error",
"translation": "Opis kanału jest za długi."
"translation": "Cel kanału jest za długi."
},
{
"id": "app.import.validate_channel_import_data.team_missing.error",
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "Brak wymaganej właściwości Post: User."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "Właściwość CreateAt musi być wyższa niż parent post CreateAt."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "Brak wymaganej właściwości: create_at."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "Właściwość CreateAt nie może być zero."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "Właściwość EmojiName jest dłuższa niż maksymalna dozwolona długość."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "Brak wymaganej właściwości: EmojiName."
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "Brak wymaganej właściwości: User."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "Właściwość CreateAt musi być wyższa niż parent post CreateAt."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "Brak wymaganej właściwości Post: create_at."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "Właściwość Post CreateAt nie może być zero jeśli podany."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "Właściwość wiadomości Post jest dłuższa niz dozwolona długość."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "Brak wymaganej właściwości: Message."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "Brak wymaganej właściwości: User."
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "Drużyna allowed_domains jest za długa."
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "Pozycja użytkownika jest za długa."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Invalid profile image."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "Nieprawidłowe role użytkownika."
@@ -4356,7 +4416,7 @@
},
{
"id": "model.channel.is_valid.purpose.app_error",
"translation": "Nieprawidłowe przeznaczenie"
"translation": "Nieprawidłowy cel"
},
{
"id": "model.channel.is_valid.type.app_error",
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "Do musi być większe niż od"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Invalid atmos/camo image proxy options for service settings. Must be set to your shared key."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "Nie można odblokować masowych emaili gdy klastrowanie jest odblokowane."
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "Nieprawidłowa szerokość miniaturki dla ustawień plików. Musi być liczbą większą od 0."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Invalid image proxy type for service settings."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "Pole AD/LDAP \"BaseDN\" jest wymagane."
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "Nie można usunąć identyfikatora dostępu"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "Nie można usunąć identyfikatora dostępu"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "Nie można usunąć identyfikatora dostępu"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "Nie mogliśmy zapisać identyfikatora dostępu."
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "Wystąpił błąd podczas wyszukiwania identyfikatora dostępu"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "Nie udało się policzyć przychodzących webhooków"

Просмотреть файл

@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "Gerenciamento de Canais Públicos e criação é restrito apenas para o Time e Administradores do Sistema."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "Este canal foi convertido para um Canal Público e membros de qualquer equipe podem se juntar."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "Este canal foi convertido para um Canal Privado."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "Deve-se usar a API de serviço createDirectChannel para criação do canal de mensagens diretas"
@@ -3352,7 +3360,7 @@
},
{
"id": "app.import.validate_post_import_data.create_at_zero.error",
"translation": "A propriedade CreateAt da mensagem não pode ser zero se informado."
"translation": "A propriedade CreateAt do Post não pode ser zero."
},
{
"id": "app.import.validate_post_import_data.message_length.error",
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "Propriedade obrigatória do Post não foi informada: User."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "A propriedade CreateAt da Reação deve ser maior que CreateAt do post pai."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "Propriedade obrigatória da Reação não foi informada: create_at."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "A propriedade CreateAt da Reação não pode ser zero."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "A propriedade EmojiName da Reação é maior que o comprimento máximo permitido."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "Propriedade obrigatória da Reação não foi informada: EmojiName."
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "Propriedade obrigatória da Reação não foi informada: User."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "A propriedade CreateAt da Resposta deve ser maior que CreateAt do post pai."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "Propriedade obrigatória da Resposta não foi informada: create_at."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "A propriedade CreateAt da Resposta não pode ser zero."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "A propriedade Message da Resposta é maior que o comprimento máximo permitido."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "Propriedade obrigatória da Resposta não foi informada: Message."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "Propriedade obrigatória da Resposta não foi informada: User."
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "Equipe allowed_domains é muito longo."
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "O Cargo do usuário é muito longo."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Imagem do perfil inválida."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "As funções de usuário não são válidas."
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "Para precisa ser maior que De"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Invalid atmos/camo image proxy options for service settings. Must be set to your shared key."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "Não é possível ativar email em lote quando clustering está ativo."
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "Definição da largura do thumbnail inválida. Deve ser um número positivo."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Invalid image proxy type for service settings."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "O campo \"BaseDN\" no AD/LDAP é requerido."
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "Não foi possível obter o token de acesso individual"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "Não foi possível obter todos os tokens de acesso individual"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "Não foi possível obter o token de acesso inidividual pelo token"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "Não foi possível salvar o token de acesso individual"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "Encontramos um erro ao procurar os tokens de acesso"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "Não foi possível contar os webhooks entrada"

Просмотреть файл

@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "Создание и управление Публичными Каналами возможно Командой и Системными Администраторами."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "This channel has been converted to a Public Channel and can be joined by any team member."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "This channel has been converted to a Private Channel."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "Нужно использовать createDirectChannel из API для создания канала личных сообщений"
@@ -2312,7 +2320,7 @@
},
{
"id": "api.team.remove_user_from_team.removed",
"translation": "%v удален из канала."
"translation": "%v удален из команды."
},
{
"id": "api.team.signup_team.email_disabled.app_error",
@@ -3352,7 +3360,7 @@
},
{
"id": "app.import.validate_post_import_data.create_at_zero.error",
"translation": "Post CreateAt property must not be zero if provided."
"translation": "Post CreateAt property must not be zero."
},
{
"id": "app.import.validate_post_import_data.message_length.error",
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "Отсутствует необходимое поле для Post: User."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "Reaction CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "Отсутствует необходимое поле для Post: create_at."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "Reaction CreateAt property must not be zero."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "Post Message длиннее, чем максимально разрешённая длина."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "Отсутствует необходимое поле для Post: User."
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "Отсутствует необходимое поле для Post: User."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "Reply CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "Отсутствует необходимое поле для Post: create_at."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "Reply CreateAt property must not be zero."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "Post Message длиннее, чем максимально разрешённая длина."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "Отсутствует необходимое поле для Post: Message."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "Отсутствует необходимое поле для Post: User."
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "Свойство Team allowed_domains слишком длинное."
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "Расположение пользователя слишком длинное."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Invalid profile image."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "Неверные роли пользователя."
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "\"До\" должно быть больше, чем \"С\""
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Invalid atmos/camo image proxy options for service settings. Must be set to your shared key."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "Невозможно включить пакетную обработку почты при включенной кластеризации."
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "Неверная ширина миниатюры в настройках файлов. Число должно быть положительным."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Invalid image proxy type for service settings."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "Требуется поле AD/LDAP \"BaseDN\"."
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "Не удалось получить персональный токен доступа"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "Не удалось получить персональный токен доступа"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "Не удалось получить персональный токен доступа по токену"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "Не удалось сохранить персональный токен доступа"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "Возникла ошибка с обнаружением токена доступа"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "Не удалось подсчитать входящие вебхуки"

Просмотреть файл

@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "Herkese açık kanal ekleme ve yönetim işlemlerini yalnız Takım ve Sistem Yöneticileri yapabilir."
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "Bu kanal Herkese Açık Kanala dönüştürüldü ve isteyen her takım üyesi katılabilir."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "Bu kanal Özel Kanala dönüştürüldü."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "Doğrudan ileti kanalı eklemek için createDirectChannel API hizmeti kullanılmalıdır"
@@ -3352,7 +3360,7 @@
},
{
"id": "app.import.validate_post_import_data.create_at_zero.error",
"translation": "İleti oluşturulma zamanı belirtilmiş ise 0 olmamalıdır."
"translation": "İleti Oluşturulma Zamanı özelliği sıfır olamaz."
},
{
"id": "app.import.validate_post_import_data.message_length.error",
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "Zorunlu ileti özelliği eksik: Kullanıcı."
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "Tepki Oluşturulma Zamanı özelliği üst iletinin Oluşturulma Zamanından sonra olmalıdır."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "Zorunlu tepki özelliği eksik: Oluşturulma Zamanı."
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "Tepki Oluşturulma Zamanı özelliği sıfır olamaz."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "Tepki EmojiAdı özelliği izin verilen uzunluğu aşıyor."
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "Zorunlu tepki özelliği eksik: EmojiAdı."
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "Zorunlu tepki özelliği eksik: Kullanıcı."
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "Yanıt Oluşturulma Zamanı özelliği üst iletinin Oluşturulma Zamanından sonra olmalıdır."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "Zorunlu yanıt özelliği eksik: Oluşturulma Zamanı."
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "Yanıt Oluşturulma Zamanı özelliği sıfır olamaz."
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "Yanıt metni özelliği izin verilen uzunluğu aşıyor."
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "Zorunlu yanıt özelliği eksik: İleti."
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "Zorunlu yanıt özelliği eksik: Kullanıcı."
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "Takım için izin verilen etki alanları çok uzun."
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "Kullanıcının Konumu çok uzun."
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Profil görseli geçersiz."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "Kullanıcının Rolleri geçersiz."
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "Bitiş, başlangıç zamanından büyük olmalıdır"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Hizmet ayarlarında atmos/camo görsel vekil sunucusu ayarları geçersiz. Paylaşılmış anahtarınıza ayarlanmalıdır."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "Küme özelliği etkinleştirilmişken toplu e-posta etkinleştirilemez."
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "Küçük görsel genişliği dosya ayarı geçersiz. Sıfır ya da pozitif bir sayı olmalı."
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Hizmet ayarlarında görsel vekil sunucu türü geçersiz."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "\"BaseDN\" AD/LDAP alanı zorunludur."
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "Kişisel erişim kodu alınamadı"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "Tüm kişisel erişim kodları alınamadı"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "Koda göre kişisel erişim kodu alınamadı"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "Kişisel erişim kodu kaydedilemedi"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "Kullanıcı erişim kodları aranırken bir sorun çıktı"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "Gelen web bağlantıları sayılamadı"

Просмотреть файл

@@ -153,7 +153,7 @@
},
{
"id": "api.channel.add_member.added",
"translation": "%v 由 %v 邀请加入频道"
"translation": "%v 由 %v 邀请加入频道"
},
{
"id": "api.channel.add_member.find_channel.app_error",
@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "只有团队和系统管理员能创建与管理公开频道。"
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "此频道已转换到公共频道并允许任何团队成员加入。"
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "此频道已转换到私有频道。"
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "必须使用 createDirectChannel API 创建私信频道"
@@ -2176,7 +2184,7 @@
},
{
"id": "api.team.add_user_to_team.added",
"translation": "%v 由 %v 邀请加入到团队"
"translation": "%v 由 %v 邀请加入到团队"
},
{
"id": "api.team.add_user_to_team.missing_parameter.app_error",
@@ -2312,7 +2320,7 @@
},
{
"id": "api.team.remove_user_from_team.removed",
"translation": "%v 已从频道移出。"
"translation": "%v 已移出团队。"
},
{
"id": "api.team.signup_team.email_disabled.app_error",
@@ -3352,7 +3360,7 @@
},
{
"id": "app.import.validate_post_import_data.create_at_zero.error",
"translation": "如果提供消息 CreateAt 属性不能为零。"
"translation": "消息 CreateAt 属性不能为零。"
},
{
"id": "app.import.validate_post_import_data.message_length.error",
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "缺少消息必须属性User。"
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "Reaction CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "缺少反应必须属性create_at。"
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "反应 CreateAt 属性不能为零。"
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "反应 EmojiName 属性超过允许的最大长度。"
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "缺少反应必须属性User。"
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "缺少反应必须属性User。"
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "Reply CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "缺少回复必须属性create_at。"
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "回复 CreateAt 属性不能为零。"
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "回复消息属性超过允许的最大长度。"
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "缺少回复必须属性Message。"
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "缺少回复必须属性User。"
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "团队 allowed_domains 过长。"
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "用户职位过长。"
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "无效个人资料图片。"
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "无效用户角色。"
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "必须比From参数大"
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "无效的 atmos/camo 图片代理设定。必须设为您的共享密钥。"
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "当机群启用时没法启动批量电子邮件。"
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "文件设置时缩略图宽度无效。必须是正数。"
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "无效的图片代理类型服务设定。"
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "AD/LDAP 栏 \"BaseDN\" 为必须。"
@@ -5336,7 +5404,7 @@
},
{
"id": "model.user.is_valid.position.app_error",
"translation": "无效位置:不能超过 35 个字符。"
"translation": "无效位置:不能超过 128 个字符。"
},
{
"id": "model.user.is_valid.pwd.app_error",
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "我们无法获取个人访问令牌"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "我们无法获取所有个人访问令牌"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "我们无法从令牌获取个人访问令牌"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "我们无法保存个人访问令牌"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "我们查找用户访问令牌时遇到一个错误"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "我们无法计算传入的 webhooks"

Просмотреть файл

@@ -199,6 +199,14 @@
"id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
"translation": "只有團隊和系統管理員能建立與管理公開頻道。"
},
{
"id": "api.channel.change_channel_privacy.private_to_public",
"translation": "This channel has been converted to a Public Channel and can be joined by any team member."
},
{
"id": "api.channel.change_channel_privacy.public_to_private",
"translation": "This channel has been converted to a Private Channel."
},
{
"id": "api.channel.create_channel.direct_channel.app_error",
"translation": "必須使用 createDirectChannel API 服務來建立直接訊息頻道"
@@ -3370,6 +3378,54 @@
"id": "app.import.validate_post_import_data.user_missing.error",
"translation": "缺少必要的訊息屬性:使用者。"
},
{
"id": "app.import.validate_reaction_import_data.create_at_before_parent.error",
"translation": "Reaction CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reaction_import_data.create_at_missing.error",
"translation": "缺少必要的訊息屬性:建立日期。"
},
{
"id": "app.import.validate_reaction_import_data.create_at_zero.error",
"translation": "如果有提供訊息建立時間,該值不能為 0。"
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_length.error",
"translation": "訊息屬性長度超過允許的最大長度"
},
{
"id": "app.import.validate_reaction_import_data.emoji_name_missing.error",
"translation": "缺少必要的訊息屬性:使用者。"
},
{
"id": "app.import.validate_reaction_import_data.user_missing.error",
"translation": "缺少必要的訊息屬性:使用者。"
},
{
"id": "app.import.validate_reply_import_data.create_at_before_parent.error",
"translation": "Reply CreateAt property must be greater than the parent post CreateAt."
},
{
"id": "app.import.validate_reply_import_data.create_at_missing.error",
"translation": "缺少必要的訊息屬性:建立日期。"
},
{
"id": "app.import.validate_reply_import_data.create_at_zero.error",
"translation": "如果有提供訊息建立時間,該值不能為 0。"
},
{
"id": "app.import.validate_reply_import_data.message_length.error",
"translation": "訊息屬性長度超過允許的最大長度"
},
{
"id": "app.import.validate_reply_import_data.message_missing.error",
"translation": "缺少必要的訊息屬性:訊息。"
},
{
"id": "app.import.validate_reply_import_data.user_missing.error",
"translation": "缺少必要的訊息屬性:使用者。"
},
{
"id": "app.import.validate_team_import_data.allowed_domains_length.error",
"translation": "團隊允許網域過長。"
@@ -3506,6 +3562,10 @@
"id": "app.import.validate_user_import_data.position_length.error",
"translation": "使用者職位過長。"
},
{
"id": "app.import.validate_user_import_data.profile_image.error",
"translation": "Invalid profile image."
},
{
"id": "app.import.validate_user_import_data.roles_invalid.error",
"translation": "無效的使用者角色。"
@@ -4582,6 +4642,10 @@
"id": "model.compliance.is_valid.start_end_at.app_error",
"translation": "\"到\"必須大於\"起始\""
},
{
"id": "model.config.is_valid.atmos_camo_image_proxy_options.app_error",
"translation": "Invalid atmos/camo image proxy options for service settings. Must be set to your shared key."
},
{
"id": "model.config.is_valid.cluster_email_batching.app_error",
"translation": "啟用叢集時無法啟用批次郵件"
@@ -4694,6 +4758,10 @@
"id": "model.config.is_valid.file_thumb_width.app_error",
"translation": "檔案設定中縮圖寬度無效。必須為正數。"
},
{
"id": "model.config.is_valid.image_proxy_type.app_error",
"translation": "Invalid image proxy type for service settings."
},
{
"id": "model.config.is_valid.ldap_basedn",
"translation": "AD/LDAP 欄位 \"BaseDN\" 為必須欄位。"
@@ -6778,6 +6846,10 @@
"id": "store.sql_user_access_token.get.app_error",
"translation": "無法取得個人存取 Token"
},
{
"id": "store.sql_user_access_token.get_all.app_error",
"translation": "無法取得個人存取 Token"
},
{
"id": "store.sql_user_access_token.get_by_token.app_error",
"translation": "無法根據 Token 取得個人存取 Token"
@@ -6790,6 +6862,10 @@
"id": "store.sql_user_access_token.save.app_error",
"translation": "無法刪除儲存個人存取 Token"
},
{
"id": "store.sql_user_access_token.search.app_error",
"translation": "尋找存取 Token 時遇到錯誤"
},
{
"id": "store.sql_webhooks.analytics_incoming_count.app_error",
"translation": "無法計算傳入的 Webhook"

Просмотреть файл

@@ -74,41 +74,23 @@ func (me *AccessData) IsExpired() bool {
}
func (ad *AccessData) ToJson() string {
b, err := json.Marshal(ad)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(ad)
return string(b)
}
func AccessDataFromJson(data io.Reader) *AccessData {
decoder := json.NewDecoder(data)
var ad AccessData
err := decoder.Decode(&ad)
if err == nil {
return &ad
} else {
return nil
}
var ad *AccessData
json.NewDecoder(data).Decode(&ad)
return ad
}
func (ar *AccessResponse) ToJson() string {
b, err := json.Marshal(ar)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(ar)
return string(b)
}
func AccessResponseFromJson(data io.Reader) *AccessResponse {
decoder := json.NewDecoder(data)
var ar AccessResponse
err := decoder.Decode(&ar)
if err == nil {
return &ar
} else {
return nil
}
var ar *AccessResponse
json.NewDecoder(data).Decode(&ar)
return ar
}

Просмотреть файл

@@ -16,23 +16,14 @@ type AnalyticsRow struct {
type AnalyticsRows []*AnalyticsRow
func (me *AnalyticsRow) ToJson() string {
b, err := json.Marshal(me)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(me)
return string(b)
}
func AnalyticsRowFromJson(data io.Reader) *AnalyticsRow {
decoder := json.NewDecoder(data)
var me AnalyticsRow
err := decoder.Decode(&me)
if err == nil {
return &me
} else {
return nil
}
var me *AnalyticsRow
json.NewDecoder(data).Decode(&me)
return me
}
func (me AnalyticsRows) ToJson() string {
@@ -44,12 +35,7 @@ func (me AnalyticsRows) ToJson() string {
}
func AnalyticsRowsFromJson(data io.Reader) AnalyticsRows {
decoder := json.NewDecoder(data)
var me AnalyticsRows
err := decoder.Decode(&me)
if err == nil {
return me
} else {
return nil
}
json.NewDecoder(data).Decode(&me)
return me
}

Просмотреть файл

@@ -19,21 +19,12 @@ type Audit struct {
}
func (o *Audit) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func AuditFromJson(data io.Reader) *Audit {
decoder := json.NewDecoder(data)
var o Audit
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *Audit
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -28,12 +28,7 @@ func (o Audits) ToJson() string {
}
func AuditsFromJson(data io.Reader) Audits {
decoder := json.NewDecoder(data)
var o Audits
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -115,43 +115,25 @@ func (ad *AuthData) PreSave() {
}
func (ad *AuthData) ToJson() string {
b, err := json.Marshal(ad)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(ad)
return string(b)
}
func AuthDataFromJson(data io.Reader) *AuthData {
decoder := json.NewDecoder(data)
var ad AuthData
err := decoder.Decode(&ad)
if err == nil {
return &ad
} else {
return nil
}
var ad *AuthData
json.NewDecoder(data).Decode(&ad)
return ad
}
func (ar *AuthorizeRequest) ToJson() string {
b, err := json.Marshal(ar)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(ar)
return string(b)
}
func AuthorizeRequestFromJson(data io.Reader) *AuthorizeRequest {
decoder := json.NewDecoder(data)
var ar AuthorizeRequest
err := decoder.Decode(&ar)
if err == nil {
return &ar
} else {
return nil
}
var ar *AuthorizeRequest
json.NewDecoder(data).Decode(&ar)
return ar
}
func (ad *AuthData) IsExpired() bool {

Просмотреть файл

@@ -61,43 +61,25 @@ func (o *Channel) DeepCopy() *Channel {
}
func (o *Channel) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func (o *ChannelPatch) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func ChannelFromJson(data io.Reader) *Channel {
decoder := json.NewDecoder(data)
var o Channel
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *Channel
json.NewDecoder(data).Decode(&o)
return o
}
func ChannelPatchFromJson(data io.Reader) *ChannelPatch {
decoder := json.NewDecoder(data)
var o ChannelPatch
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *ChannelPatch
json.NewDecoder(data).Decode(&o)
return o
}
func (o *Channel) Etag() string {

Просмотреть файл

@@ -43,21 +43,12 @@ func (o *ChannelCounts) Etag() string {
}
func (o *ChannelCounts) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func ChannelCountsFromJson(data io.Reader) *ChannelCounts {
decoder := json.NewDecoder(data)
var o ChannelCounts
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *ChannelCounts
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -23,21 +23,12 @@ func (o *ChannelData) Etag() string {
}
func (o *ChannelData) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func ChannelDataFromJson(data io.Reader) *ChannelData {
decoder := json.NewDecoder(data)
var o ChannelData
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *ChannelData
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -41,23 +41,13 @@ func (o *ChannelList) Etag() string {
}
func ChannelListFromJson(data io.Reader) *ChannelList {
decoder := json.NewDecoder(data)
var o ChannelList
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *ChannelList
json.NewDecoder(data).Decode(&o)
return o
}
func ChannelSliceFromJson(data io.Reader) []*Channel {
decoder := json.NewDecoder(data)
var o []*Channel
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -49,54 +49,31 @@ func (o *ChannelMembers) ToJson() string {
}
func (o *ChannelUnread) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func ChannelMembersFromJson(data io.Reader) *ChannelMembers {
decoder := json.NewDecoder(data)
var o ChannelMembers
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *ChannelMembers
json.NewDecoder(data).Decode(&o)
return o
}
func ChannelUnreadFromJson(data io.Reader) *ChannelUnread {
decoder := json.NewDecoder(data)
var o ChannelUnread
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *ChannelUnread
json.NewDecoder(data).Decode(&o)
return o
}
func (o *ChannelMember) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func ChannelMemberFromJson(data io.Reader) *ChannelMember {
decoder := json.NewDecoder(data)
var o ChannelMember
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *ChannelMember
json.NewDecoder(data).Decode(&o)
return o
}
func (o *ChannelMember) IsValid() *AppError {

Просмотреть файл

@@ -14,22 +14,13 @@ type ChannelSearch struct {
// ToJson convert a Channel to a json string
func (c *ChannelSearch) ToJson() string {
b, err := json.Marshal(c)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(c)
return string(b)
}
// ChannelSearchFromJson will decode the input and return a Channel
func ChannelSearchFromJson(data io.Reader) *ChannelSearch {
decoder := json.NewDecoder(data)
var cs ChannelSearch
err := decoder.Decode(&cs)
if err == nil {
return &cs
} else {
return nil
}
var cs *ChannelSearch
json.NewDecoder(data).Decode(&cs)
return cs
}

Просмотреть файл

@@ -14,21 +14,12 @@ type ChannelStats struct {
}
func (o *ChannelStats) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func ChannelStatsFromJson(data io.Reader) *ChannelStats {
decoder := json.NewDecoder(data)
var o ChannelStats
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *ChannelStats
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -14,23 +14,14 @@ type ChannelView struct {
}
func (o *ChannelView) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func ChannelViewFromJson(data io.Reader) *ChannelView {
decoder := json.NewDecoder(data)
var o ChannelView
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *ChannelView
json.NewDecoder(data).Decode(&o)
return o
}
type ChannelViewResponse struct {
@@ -39,21 +30,12 @@ type ChannelViewResponse struct {
}
func (o *ChannelViewResponse) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func ChannelViewResponseFromJson(data io.Reader) *ChannelViewResponse {
decoder := json.NewDecoder(data)
var o ChannelViewResponse
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *ChannelViewResponse
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -18,12 +18,8 @@ type ClusterInfo struct {
}
func (me *ClusterInfo) ToJson() string {
b, err := json.Marshal(me)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(me)
return string(b)
}
func (me *ClusterInfo) Copy() *ClusterInfo {
@@ -32,22 +28,14 @@ func (me *ClusterInfo) Copy() *ClusterInfo {
}
func ClusterInfoFromJson(data io.Reader) *ClusterInfo {
decoder := json.NewDecoder(data)
var me ClusterInfo
err := decoder.Decode(&me)
if err == nil {
return &me
} else {
return nil
}
var me *ClusterInfo
json.NewDecoder(data).Decode(&me)
return me
}
func ClusterInfosToJson(objmap []*ClusterInfo) string {
if b, err := json.Marshal(objmap); err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(objmap)
return string(b)
}
func ClusterInfosFromJson(data io.Reader) []*ClusterInfo {

Просмотреть файл

@@ -28,5 +28,4 @@ func TestClusterInfosJson(t *testing.T) {
if clusterInfos[0].IpAddress != result[0].IpAddress {
t.Fatal("Ids do not match")
}
}

Просмотреть файл

@@ -36,21 +36,12 @@ type ClusterMessage struct {
}
func (o *ClusterMessage) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func ClusterMessageFromJson(data io.Reader) *ClusterMessage {
decoder := json.NewDecoder(data)
var o ClusterMessage
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *ClusterMessage
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -16,21 +16,12 @@ type ClusterStats struct {
}
func (me *ClusterStats) ToJson() string {
b, err := json.Marshal(me)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(me)
return string(b)
}
func ClusterStatsFromJson(data io.Reader) *ClusterStats {
decoder := json.NewDecoder(data)
var me ClusterStats
err := decoder.Decode(&me)
if err == nil {
return &me
} else {
return nil
}
var me *ClusterStats
json.NewDecoder(data).Decode(&me)
return me
}

Просмотреть файл

@@ -38,43 +38,25 @@ type Command struct {
}
func (o *Command) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func CommandFromJson(data io.Reader) *Command {
decoder := json.NewDecoder(data)
var o Command
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *Command
json.NewDecoder(data).Decode(&o)
return o
}
func CommandListToJson(l []*Command) string {
b, err := json.Marshal(l)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(l)
return string(b)
}
func CommandListFromJson(data io.Reader) []*Command {
decoder := json.NewDecoder(data)
var o []*Command
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
json.NewDecoder(data).Decode(&o)
return o
}
func (o *Command) IsValid() *AppError {

Просмотреть файл

@@ -23,21 +23,12 @@ type CommandArgs struct {
}
func (o *CommandArgs) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func CommandArgsFromJson(data io.Reader) *CommandArgs {
decoder := json.NewDecoder(data)
var o CommandArgs
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *CommandArgs
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -27,12 +27,8 @@ type CommandResponse struct {
}
func (o *CommandResponse) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func CommandResponseFromHTTPBody(contentType string, body io.Reader) *CommandResponse {

Просмотреть файл

@@ -38,12 +38,8 @@ type Compliance struct {
type Compliances []Compliance
func (o *Compliance) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func (me *Compliance) PreSave() {
@@ -56,7 +52,7 @@ func (me *Compliance) PreSave() {
}
me.Count = 0
me.Emails = strings.ToLower(me.Emails)
me.Emails = NormalizeEmail(me.Emails)
me.Keywords = strings.ToLower(me.Keywords)
me.CreateAt = GetMillis()
@@ -103,14 +99,9 @@ func (me *Compliance) IsValid() *AppError {
}
func ComplianceFromJson(data io.Reader) *Compliance {
decoder := json.NewDecoder(data)
var o Compliance
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *Compliance
json.NewDecoder(data).Decode(&o)
return o
}
func (o Compliances) ToJson() string {
@@ -122,12 +113,7 @@ func (o Compliances) ToJson() string {
}
func CompliancesFromJson(data io.Reader) Compliances {
decoder := json.NewDecoder(data)
var o Compliances
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -802,7 +802,8 @@ type RateLimitSettings struct {
PerSec *int
MaxBurst *int
MemoryStoreSize *int
VaryByRemoteAddr bool
VaryByRemoteAddr *bool
VaryByUser *bool
VaryByHeader string
}
@@ -822,6 +823,14 @@ func (s *RateLimitSettings) SetDefaults() {
if s.MemoryStoreSize == nil {
s.MemoryStoreSize = NewInt(10000)
}
if s.VaryByRemoteAddr == nil {
s.VaryByRemoteAddr = NewBool(true)
}
if s.VaryByUser == nil {
s.VaryByUser = NewBool(false)
}
}
type PrivacySettings struct {
@@ -1681,12 +1690,8 @@ func (o *Config) Clone() *Config {
}
func (o *Config) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func (o *Config) GetSSOService(service string) *SSOSettings {
@@ -1703,14 +1708,9 @@ func (o *Config) GetSSOService(service string) *SSOSettings {
}
func ConfigFromJson(data io.Reader) *Config {
decoder := json.NewDecoder(data)
var o Config
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *Config
json.NewDecoder(data).Decode(&o)
return o
}
func (o *Config) SetDefaults() {

Просмотреть файл

@@ -16,21 +16,12 @@ type DataRetentionPolicy struct {
}
func (me *DataRetentionPolicy) ToJson() string {
b, err := json.Marshal(me)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(me)
return string(b)
}
func DataRetentionPolicyFromJson(data io.Reader) *DataRetentionPolicy {
decoder := json.NewDecoder(data)
var me DataRetentionPolicy
err := decoder.Decode(&me)
if err == nil {
return &me
} else {
return nil
}
var me *DataRetentionPolicy
json.NewDecoder(data).Decode(&me)
return me
}

Просмотреть файл

@@ -61,41 +61,23 @@ func (emoji *Emoji) PreUpdate() {
}
func (emoji *Emoji) ToJson() string {
b, err := json.Marshal(emoji)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(emoji)
return string(b)
}
func EmojiFromJson(data io.Reader) *Emoji {
decoder := json.NewDecoder(data)
var emoji Emoji
err := decoder.Decode(&emoji)
if err == nil {
return &emoji
} else {
return nil
}
var emoji *Emoji
json.NewDecoder(data).Decode(&emoji)
return emoji
}
func EmojiListToJson(emojiList []*Emoji) string {
b, err := json.Marshal(emojiList)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(emojiList)
return string(b)
}
func EmojiListFromJson(data io.Reader) []*Emoji {
decoder := json.NewDecoder(data)
var emojiList []*Emoji
err := decoder.Decode(&emojiList)
if err == nil {
return emojiList
} else {
return nil
}
json.NewDecoder(data).Decode(&emojiList)
return emojiList
}

Просмотреть файл

@@ -14,21 +14,12 @@ type EmojiSearch struct {
}
func (es *EmojiSearch) ToJson() string {
b, err := json.Marshal(es)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(es)
return string(b)
}
func EmojiSearchFromJson(data io.Reader) *EmojiSearch {
decoder := json.NewDecoder(data)
var es EmojiSearch
err := decoder.Decode(&es)
if err == nil {
return &es
} else {
return nil
}
var es *EmojiSearch
json.NewDecoder(data).Decode(&es)
return es
}

Просмотреть файл

@@ -23,21 +23,12 @@ type FileUploadResponse struct {
}
func FileUploadResponseFromJson(data io.Reader) *FileUploadResponse {
decoder := json.NewDecoder(data)
var o FileUploadResponse
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *FileUploadResponse
json.NewDecoder(data).Decode(&o)
return o
}
func (o *FileUploadResponse) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}

Просмотреть файл

@@ -35,12 +35,8 @@ type FileInfo struct {
}
func (info *FileInfo) ToJson() string {
b, err := json.Marshal(info)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(info)
return string(b)
}
func FileInfoFromJson(data io.Reader) *FileInfo {
@@ -55,12 +51,8 @@ func FileInfoFromJson(data io.Reader) *FileInfo {
}
func FileInfosToJson(infos []*FileInfo) string {
b, err := json.Marshal(infos)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(infos)
return string(b)
}
func FileInfosFromJson(data io.Reader) []*FileInfo {

Просмотреть файл

@@ -40,43 +40,25 @@ type IncomingWebhookRequest struct {
}
func (o *IncomingWebhook) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func IncomingWebhookFromJson(data io.Reader) *IncomingWebhook {
decoder := json.NewDecoder(data)
var o IncomingWebhook
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *IncomingWebhook
json.NewDecoder(data).Decode(&o)
return o
}
func IncomingWebhookListToJson(l []*IncomingWebhook) string {
b, err := json.Marshal(l)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(l)
return string(b)
}
func IncomingWebhookListFromJson(data io.Reader) []*IncomingWebhook {
decoder := json.NewDecoder(data)
var o []*IncomingWebhook
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
json.NewDecoder(data).Decode(&o)
return o
}
func (o *IncomingWebhook) IsValid() *AppError {

Просмотреть файл

@@ -19,21 +19,12 @@ type InitialLoad struct {
}
func (me *InitialLoad) ToJson() string {
b, err := json.Marshal(me)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(me)
return string(b)
}
func InitialLoadFromJson(data io.Reader) *InitialLoad {
decoder := json.NewDecoder(data)
var o InitialLoad
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *InitialLoad
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -71,11 +71,8 @@ func (j *Job) IsValid() *AppError {
}
func (js *Job) ToJson() string {
if b, err := json.Marshal(js); err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(js)
return string(b)
}
func JobFromJson(data io.Reader) *Job {
@@ -88,11 +85,8 @@ func JobFromJson(data io.Reader) *Job {
}
func JobsToJson(jobs []*Job) string {
if b, err := json.Marshal(jobs); err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(jobs)
return string(b)
}
func JobsFromJson(data io.Reader) []*Job {
@@ -105,11 +99,8 @@ func JobsFromJson(data io.Reader) []*Job {
}
func (js *Job) DataToJson() string {
if b, err := json.Marshal(js.Data); err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(js.Data)
return string(b)
}
type Worker interface {

Просмотреть файл

@@ -169,23 +169,14 @@ func (l *License) IsStarted() bool {
}
func (l *License) ToJson() string {
b, err := json.Marshal(l)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(l)
return string(b)
}
func LicenseFromJson(data io.Reader) *License {
decoder := json.NewDecoder(data)
var o License
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *License
json.NewDecoder(data).Decode(&o)
return o
}
func (lr *LicenseRecord) IsValid() *AppError {

Просмотреть файл

@@ -142,43 +142,25 @@ type ManifestWebapp struct {
}
func (m *Manifest) ToJson() string {
b, err := json.Marshal(m)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(m)
return string(b)
}
func ManifestListToJson(m []*Manifest) string {
b, err := json.Marshal(m)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(m)
return string(b)
}
func ManifestFromJson(data io.Reader) *Manifest {
decoder := json.NewDecoder(data)
var m Manifest
err := decoder.Decode(&m)
if err == nil {
return &m
} else {
return nil
}
var m *Manifest
json.NewDecoder(data).Decode(&m)
return m
}
func ManifestListFromJson(data io.Reader) []*Manifest {
decoder := json.NewDecoder(data)
var manifests []*Manifest
err := decoder.Decode(&manifests)
if err == nil {
return manifests
} else {
return nil
}
json.NewDecoder(data).Decode(&manifests)
return manifests
}
func (m *Manifest) HasClient() bool {

Просмотреть файл

@@ -14,21 +14,12 @@ type MfaSecret struct {
}
func (me *MfaSecret) ToJson() string {
b, err := json.Marshal(me)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(me)
return string(b)
}
func MfaSecretFromJson(data io.Reader) *MfaSecret {
decoder := json.NewDecoder(data)
var me MfaSecret
err := decoder.Decode(&me)
if err == nil {
return &me
} else {
return nil
}
var me *MfaSecret
json.NewDecoder(data).Decode(&me)
return me
}

Просмотреть файл

@@ -110,12 +110,8 @@ func (a *OAuthApp) PreUpdate() {
// ToJson convert a User to a json string
func (a *OAuthApp) ToJson() string {
b, err := json.Marshal(a)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(a)
return string(b)
}
// Generate a valid strong etag so the browser can cache the results
@@ -140,52 +136,29 @@ func (a *OAuthApp) IsValidRedirectURL(url string) bool {
// OAuthAppFromJson will decode the input and return a User
func OAuthAppFromJson(data io.Reader) *OAuthApp {
decoder := json.NewDecoder(data)
var app OAuthApp
err := decoder.Decode(&app)
if err == nil {
return &app
} else {
return nil
}
var app *OAuthApp
json.NewDecoder(data).Decode(&app)
return app
}
func OAuthAppMapToJson(a map[string]*OAuthApp) string {
b, err := json.Marshal(a)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(a)
return string(b)
}
func OAuthAppMapFromJson(data io.Reader) map[string]*OAuthApp {
decoder := json.NewDecoder(data)
var apps map[string]*OAuthApp
err := decoder.Decode(&apps)
if err == nil {
return apps
} else {
return nil
}
json.NewDecoder(data).Decode(&apps)
return apps
}
func OAuthAppListToJson(l []*OAuthApp) string {
b, err := json.Marshal(l)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(l)
return string(b)
}
func OAuthAppListFromJson(data io.Reader) []*OAuthApp {
decoder := json.NewDecoder(data)
var o []*OAuthApp
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -58,12 +58,8 @@ type OutgoingWebhookResponse struct {
const OUTGOING_HOOK_RESPONSE_TYPE_COMMENT = "comment"
func (o *OutgoingWebhookPayload) ToJSON() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func (o *OutgoingWebhookPayload) ToFormValues() string {
@@ -85,63 +81,36 @@ func (o *OutgoingWebhookPayload) ToFormValues() string {
}
func (o *OutgoingWebhook) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func OutgoingWebhookFromJson(data io.Reader) *OutgoingWebhook {
decoder := json.NewDecoder(data)
var o OutgoingWebhook
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *OutgoingWebhook
json.NewDecoder(data).Decode(&o)
return o
}
func OutgoingWebhookListToJson(l []*OutgoingWebhook) string {
b, err := json.Marshal(l)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(l)
return string(b)
}
func OutgoingWebhookListFromJson(data io.Reader) []*OutgoingWebhook {
decoder := json.NewDecoder(data)
var o []*OutgoingWebhook
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
json.NewDecoder(data).Decode(&o)
return o
}
func (o *OutgoingWebhookResponse) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func OutgoingWebhookResponseFromJson(data io.Reader) *OutgoingWebhookResponse {
decoder := json.NewDecoder(data)
var o OutgoingWebhookResponse
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *OutgoingWebhookResponse
json.NewDecoder(data).Decode(&o)
return o
}
func (o *OutgoingWebhook) IsValid() *AppError {

Просмотреть файл

@@ -19,21 +19,12 @@ type PluginsResponse struct {
}
func (m *PluginsResponse) ToJson() string {
b, err := json.Marshal(m)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(m)
return string(b)
}
func PluginsResponseFromJson(data io.Reader) *PluginsResponse {
decoder := json.NewDecoder(data)
var m PluginsResponse
err := decoder.Decode(&m)
if err == nil {
return &m
} else {
return nil
}
var m *PluginsResponse
json.NewDecoder(data).Decode(&m)
return m
}

Просмотреть файл

@@ -130,14 +130,9 @@ func (o *Post) ToJson() string {
}
func PostFromJson(data io.Reader) *Post {
decoder := json.NewDecoder(data)
var o Post
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *Post
json.NewDecoder(data).Decode(&o)
return o
}
func (o *Post) Etag() string {
@@ -349,12 +344,8 @@ func (o *Post) ChannelMentions() (names []string) {
}
func (r *PostActionIntegrationRequest) ToJson() string {
b, err := json.Marshal(r)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(r)
return string(b)
}
func (o *Post) Attachments() []*SlackAttachment {

Просмотреть файл

@@ -132,12 +132,7 @@ func (o *PostList) IsChannelId(channelId string) bool {
}
func PostListFromJson(data io.Reader) *PostList {
decoder := json.NewDecoder(data)
var o PostList
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *PostList
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -47,23 +47,14 @@ type Preference struct {
}
func (o *Preference) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func PreferenceFromJson(data io.Reader) *Preference {
decoder := json.NewDecoder(data)
var o Preference
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *Preference
json.NewDecoder(data).Decode(&o)
return o
}
func (o *Preference) IsValid() *AppError {

Просмотреть файл

@@ -11,12 +11,8 @@ import (
type Preferences []Preference
func (o *Preferences) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func PreferencesFromJson(data io.Reader) (Preferences, error) {

Просмотреть файл

@@ -47,12 +47,8 @@ type PushNotification struct {
}
func (me *PushNotification) ToJson() string {
b, err := json.Marshal(me)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(me)
return string(b)
}
func (me *PushNotification) SetDeviceIdAndPlatform(deviceId string) {
@@ -66,12 +62,7 @@ func (me *PushNotification) SetDeviceIdAndPlatform(deviceId string) {
}
func PushNotificationFromJson(data io.Reader) *PushNotification {
decoder := json.NewDecoder(data)
var me PushNotification
err := decoder.Decode(&me)
if err == nil {
return &me
} else {
return nil
}
var me *PushNotification
json.NewDecoder(data).Decode(&me)
return me
}

Просмотреть файл

@@ -38,11 +38,8 @@ func NewErrorPushResponse(message string) PushResponse {
}
func (me *PushResponse) ToJson() string {
if b, err := json.Marshal(me); err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(me)
return string(b)
}
func PushResponseFromJson(data io.Reader) PushResponse {

Просмотреть файл

@@ -18,11 +18,8 @@ type Reaction struct {
}
func (o *Reaction) ToJson() string {
if b, err := json.Marshal(o); err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func ReactionFromJson(data io.Reader) *Reaction {
@@ -36,11 +33,8 @@ func ReactionFromJson(data io.Reader) *Reaction {
}
func ReactionsToJson(o []*Reaction) string {
if b, err := json.Marshal(o); err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func ReactionsFromJson(data io.Reader) []*Reaction {

Просмотреть файл

@@ -29,21 +29,12 @@ type SamlCertificateStatus struct {
}
func (s *SamlCertificateStatus) ToJson() string {
b, err := json.Marshal(s)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(s)
return string(b)
}
func SamlCertificateStatusFromJson(data io.Reader) *SamlCertificateStatus {
decoder := json.NewDecoder(data)
var status SamlCertificateStatus
err := decoder.Decode(&status)
if err == nil {
return &status
} else {
return nil
}
var status *SamlCertificateStatus
json.NewDecoder(data).Decode(&status)
return status
}

Просмотреть файл

@@ -21,12 +21,8 @@ type SearchParams struct {
}
func (o *SearchParams) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
var searchFlags = [...]string{"from", "channel", "in"}

Просмотреть файл

@@ -16,23 +16,14 @@ type SecurityBulletin struct {
type SecurityBulletins []SecurityBulletin
func (me *SecurityBulletin) ToJson() string {
b, err := json.Marshal(me)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(me)
return string(b)
}
func SecurityBulletinFromJson(data io.Reader) *SecurityBulletin {
decoder := json.NewDecoder(data)
var o SecurityBulletin
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *SecurityBulletin
json.NewDecoder(data).Decode(&o)
return o
}
func (me SecurityBulletins) ToJson() string {
@@ -44,12 +35,7 @@ func (me SecurityBulletins) ToJson() string {
}
func SecurityBulletinsFromJson(data io.Reader) SecurityBulletins {
decoder := json.NewDecoder(data)
var o SecurityBulletins
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -43,23 +43,14 @@ func (me *Session) DeepCopy() *Session {
}
func (me *Session) ToJson() string {
b, err := json.Marshal(me)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(me)
return string(b)
}
func SessionFromJson(data io.Reader) *Session {
decoder := json.NewDecoder(data)
var me Session
err := decoder.Decode(&me)
if err == nil {
return &me
} else {
return nil
}
var me *Session
json.NewDecoder(data).Decode(&me)
return me
}
func (me *Session) PreSave() {
@@ -140,12 +131,7 @@ func SessionsToJson(o []*Session) string {
}
func SessionsFromJson(data io.Reader) []*Session {
decoder := json.NewDecoder(data)
var o []*Session
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -27,43 +27,25 @@ type Status struct {
}
func (o *Status) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func StatusFromJson(data io.Reader) *Status {
decoder := json.NewDecoder(data)
var o Status
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *Status
json.NewDecoder(data).Decode(&o)
return o
}
func StatusListToJson(u []*Status) string {
b, err := json.Marshal(u)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(u)
return string(b)
}
func StatusListFromJson(data io.Reader) []*Status {
decoder := json.NewDecoder(data)
var statuses []*Status
err := decoder.Decode(&statuses)
if err == nil {
return statuses
} else {
return nil
}
json.NewDecoder(data).Decode(&statuses)
return statuses
}
func StatusMapToInterfaceMap(statusMap map[string]*Status) map[string]interface{} {

Просмотреть файл

@@ -14,21 +14,12 @@ type SuggestCommand struct {
}
func (o *SuggestCommand) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func SuggestCommandFromJson(data io.Reader) *SuggestCommand {
decoder := json.NewDecoder(data)
var o SuggestCommand
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *SuggestCommand
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -19,23 +19,14 @@ type SwitchRequest struct {
}
func (o *SwitchRequest) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func SwitchRequestFromJson(data io.Reader) *SwitchRequest {
decoder := json.NewDecoder(data)
var o SwitchRequest
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *SwitchRequest
json.NewDecoder(data).Decode(&o)
return o
}
func (o *SwitchRequest) EmailToOAuth() bool {

Просмотреть файл

@@ -22,21 +22,12 @@ type System struct {
}
func (o *System) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func SystemFromJson(data io.Reader) *System {
decoder := json.NewDecoder(data)
var o System
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *System
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -54,14 +54,9 @@ type Invites struct {
}
func InvitesFromJson(data io.Reader) *Invites {
decoder := json.NewDecoder(data)
var o Invites
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *Invites
json.NewDecoder(data).Decode(&o)
return o
}
func (o *Invites) ToEmailList() []string {
@@ -73,72 +68,41 @@ func (o *Invites) ToEmailList() []string {
}
func (o *Invites) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func (o *Team) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func TeamFromJson(data io.Reader) *Team {
decoder := json.NewDecoder(data)
var o Team
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *Team
json.NewDecoder(data).Decode(&o)
return o
}
func TeamMapToJson(u map[string]*Team) string {
b, err := json.Marshal(u)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(u)
return string(b)
}
func TeamMapFromJson(data io.Reader) map[string]*Team {
decoder := json.NewDecoder(data)
var teams map[string]*Team
err := decoder.Decode(&teams)
if err == nil {
return teams
} else {
return nil
}
json.NewDecoder(data).Decode(&teams)
return teams
}
func TeamListToJson(t []*Team) string {
b, err := json.Marshal(t)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(t)
return string(b)
}
func TeamListFromJson(data io.Reader) []*Team {
decoder := json.NewDecoder(data)
var teams []*Team
err := decoder.Decode(&teams)
if err == nil {
return teams
} else {
return nil
}
json.NewDecoder(data).Decode(&teams)
return teams
}
func (o *Team) Etag() string {

Просмотреть файл

@@ -24,43 +24,25 @@ type TeamUnread struct {
}
func (o *TeamMember) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func (o *TeamUnread) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func TeamMemberFromJson(data io.Reader) *TeamMember {
decoder := json.NewDecoder(data)
var o TeamMember
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *TeamMember
json.NewDecoder(data).Decode(&o)
return o
}
func TeamUnreadFromJson(data io.Reader) *TeamUnread {
decoder := json.NewDecoder(data)
var o TeamUnread
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *TeamUnread
json.NewDecoder(data).Decode(&o)
return o
}
func TeamMembersToJson(o []*TeamMember) string {
@@ -72,14 +54,9 @@ func TeamMembersToJson(o []*TeamMember) string {
}
func TeamMembersFromJson(data io.Reader) []*TeamMember {
decoder := json.NewDecoder(data)
var o []*TeamMember
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
json.NewDecoder(data).Decode(&o)
return o
}
func TeamsUnreadToJson(o []*TeamUnread) string {
@@ -91,14 +68,9 @@ func TeamsUnreadToJson(o []*TeamUnread) string {
}
func TeamsUnreadFromJson(data io.Reader) []*TeamUnread {
decoder := json.NewDecoder(data)
var o []*TeamUnread
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
json.NewDecoder(data).Decode(&o)
return o
}
func (o *TeamMember) IsValid() *AppError {

Просмотреть файл

@@ -15,21 +15,12 @@ type TeamStats struct {
}
func (o *TeamStats) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func TeamStatsFromJson(data io.Reader) *TeamStats {
decoder := json.NewDecoder(data)
var o TeamStats
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *TeamStats
json.NewDecoder(data).Decode(&o)
return o
}

Просмотреть файл

@@ -162,6 +162,14 @@ func InvalidUserError(fieldName string, userId string) *AppError {
return NewAppError("User.IsValid", id, nil, details, http.StatusBadRequest)
}
func NormalizeUsername(username string) string {
return strings.ToLower(username)
}
func NormalizeEmail(email string) string {
return strings.ToLower(email)
}
// PreSave will set the Id and Username if missing. It will also fill
// in the CreateAt, UpdateAt times. It will also hash the password. It should
// be run before saving the user to the db.
@@ -178,8 +186,8 @@ func (u *User) PreSave() {
u.AuthData = nil
}
u.Username = strings.ToLower(u.Username)
u.Email = strings.ToLower(u.Email)
u.Username = NormalizeUsername(u.Username)
u.Email = NormalizeEmail(u.Email)
u.CreateAt = GetMillis()
u.UpdateAt = u.CreateAt
@@ -207,8 +215,8 @@ func (u *User) PreSave() {
// PreUpdate should be run before updating the user in the db.
func (u *User) PreUpdate() {
u.Username = strings.ToLower(u.Username)
u.Email = strings.ToLower(u.Email)
u.Username = NormalizeUsername(u.Username)
u.Email = NormalizeEmail(u.Email)
u.UpdateAt = GetMillis()
if u.AuthData != nil && *u.AuthData == "" {
@@ -298,30 +306,18 @@ func (u *User) Patch(patch *UserPatch) {
// ToJson convert a User to a json string
func (u *User) ToJson() string {
b, err := json.Marshal(u)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(u)
return string(b)
}
func (u *UserPatch) ToJson() string {
b, err := json.Marshal(u)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(u)
return string(b)
}
func (u *UserAuth) ToJson() string {
b, err := json.Marshal(u)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(u)
return string(b)
}
// Generate a valid strong etag so the browser can cache the results
@@ -483,76 +479,43 @@ func (u *User) IsSAMLUser() bool {
// UserFromJson will decode the input and return a User
func UserFromJson(data io.Reader) *User {
decoder := json.NewDecoder(data)
var user User
err := decoder.Decode(&user)
if err == nil {
return &user
} else {
return nil
}
var user *User
json.NewDecoder(data).Decode(&user)
return user
}
func UserPatchFromJson(data io.Reader) *UserPatch {
decoder := json.NewDecoder(data)
var user UserPatch
err := decoder.Decode(&user)
if err == nil {
return &user
} else {
return nil
}
var user *UserPatch
json.NewDecoder(data).Decode(&user)
return user
}
func UserAuthFromJson(data io.Reader) *UserAuth {
decoder := json.NewDecoder(data)
var user UserAuth
err := decoder.Decode(&user)
if err == nil {
return &user
} else {
return nil
}
var user *UserAuth
json.NewDecoder(data).Decode(&user)
return user
}
func UserMapToJson(u map[string]*User) string {
b, err := json.Marshal(u)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(u)
return string(b)
}
func UserMapFromJson(data io.Reader) map[string]*User {
decoder := json.NewDecoder(data)
var users map[string]*User
err := decoder.Decode(&users)
if err == nil {
return users
} else {
return nil
}
json.NewDecoder(data).Decode(&users)
return users
}
func UserListToJson(u []*User) string {
b, err := json.Marshal(u)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(u)
return string(b)
}
func UserListFromJson(data io.Reader) []*User {
decoder := json.NewDecoder(data)
var users []*User
err := decoder.Decode(&users)
if err == nil {
return users
} else {
return nil
}
json.NewDecoder(data).Decode(&users)
return users
}
// HashPassword generates a hash using the bcrypt.GenerateFromPassword
@@ -603,7 +566,7 @@ func IsValidUsername(s string) bool {
}
func CleanUsername(s string) string {
s = strings.ToLower(strings.Replace(s, " ", "-", -1))
s = NormalizeUsername(strings.Replace(s, " ", "-", -1))
for _, value := range reservedName {
if s == value {

Просмотреть файл

@@ -43,41 +43,23 @@ func (t *UserAccessToken) PreSave() {
}
func (t *UserAccessToken) ToJson() string {
b, err := json.Marshal(t)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(t)
return string(b)
}
func UserAccessTokenFromJson(data io.Reader) *UserAccessToken {
decoder := json.NewDecoder(data)
var t UserAccessToken
err := decoder.Decode(&t)
if err == nil {
return &t
} else {
return nil
}
var t *UserAccessToken
json.NewDecoder(data).Decode(&t)
return t
}
func UserAccessTokenListToJson(t []*UserAccessToken) string {
b, err := json.Marshal(t)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(t)
return string(b)
}
func UserAccessTokenListFromJson(data io.Reader) []*UserAccessToken {
decoder := json.NewDecoder(data)
var t []*UserAccessToken
err := decoder.Decode(&t)
if err == nil {
return t
} else {
return nil
}
json.NewDecoder(data).Decode(&t)
return t
}

Просмотреть файл

@@ -23,12 +23,8 @@ type UserAutocomplete struct {
}
func (o *UserAutocomplete) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func UserAutocompleteFromJson(data io.Reader) *UserAutocomplete {
@@ -43,41 +39,23 @@ func UserAutocompleteFromJson(data io.Reader) *UserAutocomplete {
}
func (o *UserAutocompleteInChannel) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func UserAutocompleteInChannelFromJson(data io.Reader) *UserAutocompleteInChannel {
decoder := json.NewDecoder(data)
var o UserAutocompleteInChannel
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *UserAutocompleteInChannel
json.NewDecoder(data).Decode(&o)
return o
}
func (o *UserAutocompleteInTeam) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
b, _ := json.Marshal(o)
return string(b)
}
func UserAutocompleteInTeamFromJson(data io.Reader) *UserAutocompleteInTeam {
decoder := json.NewDecoder(data)
var o UserAutocompleteInTeam
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
var o *UserAutocompleteInTeam
json.NewDecoder(data).Decode(&o)
return o
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше