mirror of
https://github.com/documize/community.git
synced 2025-08-07 22:45:24 +02:00
Compare commits
68 commits
Author | SHA1 | Date | |
---|---|---|---|
|
efb092ef8f | ||
|
3fc0a15f87 | ||
|
c841c85478 | ||
|
2dae03332b | ||
|
44b1f263cd | ||
|
982e16737e | ||
|
f641e42434 | ||
|
8895db56af | ||
|
acb59e1b43 | ||
|
f2ba294be8 | ||
|
69940cb7f1 | ||
|
6bfdda7178 | ||
|
027fdf108c | ||
|
1f12df76aa | ||
|
d811b88896 | ||
|
20fb853907 | ||
|
599c53a971 | ||
|
1f462ed4f7 | ||
|
9f122fa79b | ||
|
4210caca48 | ||
|
c62fa4612b | ||
|
510e1bd0bd | ||
|
a32510b8e6 | ||
|
589f3f581f | ||
|
20bba4cd7e | ||
|
cbf5f4be7d | ||
|
dc63639c99 | ||
|
26f435bdc9 | ||
|
a8a82963fa | ||
|
ab8582e807 | ||
|
4fa0566274 | ||
|
f4b45d2aa7 | ||
|
1abc5d3e52 | ||
|
6e463ff2f4 | ||
|
f80b3f3d10 | ||
|
6c218cf087 | ||
|
3d1c8a6c54 | ||
|
576fd5e604 | ||
|
62407a28b4 | ||
|
0adf6d5dc8 | ||
|
15f8a64c86 | ||
|
95c67acaa0 | ||
|
d8f66b5ffb | ||
|
c051e81a99 | ||
|
1d86b98949 | ||
|
0a1cc86907 | ||
|
a49869d35d | ||
|
848afd3263 | ||
|
b9cb99e3bb | ||
|
64261ffcf5 | ||
|
0030418707 | ||
|
0f91ee518e | ||
|
5de1b7a92e | ||
|
a2524f785e | ||
|
f16b9f3810 | ||
|
1c09771c33 | ||
|
13fc5b5015 | ||
|
76c777acc1 | ||
|
ea9ff78411 | ||
|
4a9dd47894 | ||
|
7565779ef1 | ||
|
c07e7b6afc | ||
|
88bdafcb1b | ||
|
5a3cb1b226 | ||
|
6ee8e6c7b4 | ||
|
599c464d2d | ||
|
ae77fa2275 | ||
|
610367aac5 |
435 changed files with 46256 additions and 19051 deletions
|
@ -1,10 +1,10 @@
|
|||
FROM node:lts-alpine as frontbuilder
|
||||
FROM node:16-alpine as frontbuilder
|
||||
WORKDIR /go/src/github.com/documize/community/gui
|
||||
COPY ./gui /go/src/github.com/documize/community/gui
|
||||
RUN npm --network-timeout=100000 install
|
||||
RUN npm run build -- --environment=production --output-path dist-prod --suppress-sizes true
|
||||
|
||||
FROM golang:1.17-alpine as builder
|
||||
FROM golang:1.21-alpine as builder
|
||||
WORKDIR /go/src/github.com/documize/community
|
||||
COPY . /go/src/github.com/documize/community
|
||||
COPY --from=frontbuilder /go/src/github.com/documize/community/gui/dist-prod/assets /go/src/github.com/documize/community/edition/static/public/assets
|
||||
|
@ -25,7 +25,7 @@ COPY domain/onboard/*.json /go/src/github.com/documize/community/edition/static/
|
|||
RUN env GODEBUG=tls13=1 go build -mod=vendor -o bin/documize-community ./edition/community.go
|
||||
|
||||
# build release image
|
||||
FROM alpine:3.14
|
||||
FROM alpine:3.16
|
||||
RUN apk add --no-cache ca-certificates
|
||||
COPY --from=builder /go/src/github.com/documize/community/bin/documize-community /documize
|
||||
EXPOSE 5001
|
||||
|
|
21
README.md
21
README.md
|
@ -1,4 +1,4 @@
|
|||
Documize Community is an open source, self-hosted, modern, lightweight alternative to Confluence and other similar solutions.
|
||||
Documize Community is an open source, modern, self-hosted, enterprise-grade knowledge management solution.
|
||||
|
||||
- Built for technical and non-technical users
|
||||
- Designed to unify both customer-facing and internal documentation
|
||||
|
@ -12,9 +12,9 @@ All you need to provide is your database -- PostgreSQL, Microsoft SQL Server or
|
|||
|
||||
## Latest Release
|
||||
|
||||
[Community edition: v5.4.2](https://github.com/documize/community/releases)
|
||||
[Community edition: v5.13.0](https://github.com/documize/community/releases)
|
||||
|
||||
[Community+ edition: v5.4.2](https://www.documize.com/community/get-started)
|
||||
[Community+ edition: v5.13.0](https://www.documize.com/community/get-started)
|
||||
|
||||
The Community+ edition is the "enterprise" offering with advanced capabilities and customer support:
|
||||
|
||||
|
@ -43,10 +43,11 @@ Support for AMD and ARM 64 bit architectures.
|
|||
|
||||
## Database Support
|
||||
|
||||
For all database types, Full-Text Search support (FTS) is mandatory.
|
||||
For all database types, Full-Text Search (FTS) support is mandatory.
|
||||
|
||||
- PostgreSQL (v9.6+)
|
||||
- Microsoft SQL Server (2016+ with FTS)
|
||||
- Microsoft SQL Azure (v12+)
|
||||
- MySQL (v5.7.10+ and v8.0.12+)
|
||||
- Percona (v5.7.16-10+)
|
||||
- MariaDB (10.3.0+)
|
||||
|
@ -56,14 +57,14 @@ For all database types, Full-Text Search support (FTS) is mandatory.
|
|||
- Firefox
|
||||
- Chrome
|
||||
- Safari
|
||||
- Microsoft Edge (v42+)
|
||||
- Microsoft Edge
|
||||
- Brave
|
||||
- Vivaldi
|
||||
- Opera
|
||||
|
||||
## Technology Stack
|
||||
|
||||
- Go (v1.19.2)
|
||||
- Go (v1.23.4)
|
||||
- Ember JS (v3.12.0)
|
||||
|
||||
## Authentication Options
|
||||
|
@ -83,8 +84,12 @@ Languages supported out-of-the-box:
|
|||
|
||||
- English
|
||||
- German
|
||||
- French
|
||||
- Chinese (中文)
|
||||
- Portuguese (Brazil) (Português - Brasil)
|
||||
- Japanese (日本語)
|
||||
- Italian
|
||||
- Spanish Argentinian
|
||||
|
||||
PR's welcome for additional languages.
|
||||
|
||||
|
@ -100,6 +105,6 @@ We aim to respond within two working days.
|
|||
|
||||
<https://www.documize.com>
|
||||
|
||||
This software (Documize Community Edition) is licensed under GNU AGPL v3 <http://www.gnu.org/licenses/agpl-3.0.en.html>.
|
||||
This software (Documize Community edition) is licensed under GNU AGPL v3 <http://www.gnu.org/licenses/agpl-3.0.en.html>.
|
||||
|
||||
Documize uses other open source components and we acknowledge them in [NOTICES](NOTICES.md)
|
||||
Documize Community uses other open source components and we acknowledge them in [NOTICES](NOTICES.md)
|
||||
|
|
13
build.bat
13
build.bat
|
@ -7,6 +7,7 @@ echo "Building Ember assets..."
|
|||
cd gui
|
||||
call ember b -o dist-prod/ --environment=production
|
||||
::Call allows the rest of the file to run
|
||||
cd ..
|
||||
|
||||
rd /s /q edition\static\public
|
||||
mkdir edition\static\public
|
||||
|
@ -25,18 +26,26 @@ robocopy /e /NFL /NDL /NJH gui\dist-prod\sections edition\static\public\sections
|
|||
echo "Copying i18n folder"
|
||||
robocopy /e /NFL /NDL /NJH gui\dist-prod\i18n edition\static\public\i18n
|
||||
|
||||
echo "Copying static files"
|
||||
copy gui\dist-prod\*.* edition\static
|
||||
|
||||
echo "Copying favicon.ico"
|
||||
copy gui\dist-prod\favicon.ico edition\static\public
|
||||
|
||||
echo "Copying manifest.json"
|
||||
copy gui\dist-prod\manifest.json edition\static\public
|
||||
|
||||
echo "Copying mail templates"
|
||||
rd /s /q edition\static\mail
|
||||
mkdir edition\static\mail
|
||||
copy domain\mail\*.html edition\static\mail
|
||||
|
||||
echo "Copying database templates"
|
||||
copy core\database\templates\*.html edition\static
|
||||
|
||||
rd /s /q edition\static\i18n
|
||||
mkdir edition\static\i18n
|
||||
robocopy /e /NFL /NDL /NJH gui\dist-prod\i18n\*.json edition\static\i18n
|
||||
robocopy /e /NFL /NDL /NJH gui\dist-prod\i18n edition\static\i18n *.json
|
||||
|
||||
rd /s /q edition\static\scripts
|
||||
mkdir edition\static\scripts
|
||||
|
@ -51,7 +60,7 @@ robocopy /e /NFL /NDL /NJH core\database\scripts\sqlserver edition\static\script
|
|||
|
||||
rd /s /q edition\static\onboard
|
||||
mkdir edition\static\onboard
|
||||
robocopy /e /NFL /NDL /NJH domain\onboard\*.json edition\static\onboard
|
||||
robocopy /e /NFL /NDL /NJH domain\onboard edition\static\onboard *.json
|
||||
|
||||
echo "Compiling Windows"
|
||||
set GOOS=windows
|
||||
|
|
1
build.sh
1
build.sh
|
@ -8,6 +8,7 @@ echo "Build process started $NOW"
|
|||
|
||||
echo "Building Ember assets..."
|
||||
cd gui
|
||||
# export NODE_OPTIONS=--openssl-legacy-provider
|
||||
ember build ---environment=production --output-path dist-prod --suppress-sizes true
|
||||
cd ..
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ func Check(runtime *env.Runtime) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if len(flds) == 0 {
|
||||
if len(flds) <= 5 {
|
||||
runtime.Log.Info("Database: starting setup mode for empty database")
|
||||
runtime.Flags.SiteMode = env.SiteModeSetup
|
||||
return false
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
/* community edition */
|
||||
ALTER TABLE organization ADD COLUMN `service` VARCHAR(100) NOT NULL DEFAULT 'https://api.documize.com' AFTER `domain`;
|
||||
ALTER TABLE organization ADD COLUMN `service` VARCHAR(100) NOT NULL DEFAULT '' AFTER `domain`;
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ ALTER TABLE dmz_org
|
|||
CHANGE `title` `c_title` VARCHAR(500) NOT NULL,
|
||||
CHANGE `message` `c_message` VARCHAR(500) NOT NULL,
|
||||
CHANGE `domain` `c_domain` VARCHAR(200) NOT NULL DEFAULT '',
|
||||
CHANGE `service` `c_service` VARCHAR(200) NOT NULL DEFAULT 'https://api.documize.com',
|
||||
CHANGE `service` `c_service` VARCHAR(200) NOT NULL DEFAULT '',
|
||||
CHANGE `email` `c_email` VARCHAR(500) NOT NULL DEFAULT '',
|
||||
CHANGE `allowanonymousaccess` `c_anonaccess` BOOL NOT NULL DEFAULT 0,
|
||||
CHANGE `authprovider` `c_authprovider` CHAR(20) NOT NULL DEFAULT 'documize',
|
||||
|
|
|
@ -228,7 +228,7 @@ CREATE TABLE dmz_org (
|
|||
c_title varchar(500) COLLATE ucs_basic NOT NULL,
|
||||
c_message varchar(500) COLLATE ucs_basic NOT NULL,
|
||||
c_domain varchar(200) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_service varchar(200) COLLATE ucs_basic NOT NULL DEFAULT 'https://api.documize.com',
|
||||
c_service varchar(200) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_email varchar(500) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_anonaccess bool NOT NULL DEFAULT '0',
|
||||
c_authprovider varchar(20) COLLATE ucs_basic NOT NULL DEFAULT 'documize',
|
||||
|
|
|
@ -212,7 +212,7 @@ CREATE TABLE dmz_org (
|
|||
c_title NVARCHAR(500) COLLATE Latin1_General_CS_AS NOT NULL,
|
||||
c_message NVARCHAR(500) COLLATE Latin1_General_CS_AS NOT NULL,
|
||||
c_domain NVARCHAR(200) COLLATE Latin1_General_CS_AS NOT NULL DEFAULT '',
|
||||
c_service NVARCHAR(200) COLLATE Latin1_General_CS_AS NOT NULL DEFAULT 'https://api.documize.com',
|
||||
c_service NVARCHAR(200) COLLATE Latin1_General_CS_AS NOT NULL DEFAULT '',
|
||||
c_email NVARCHAR(500) COLLATE Latin1_General_CS_AS NOT NULL DEFAULT '',
|
||||
c_anonaccess BIT NOT NULL DEFAULT '0',
|
||||
c_authprovider NVARCHAR(20) COLLATE Latin1_General_CS_AS NOT NULL DEFAULT 'documize',
|
||||
|
|
4
core/database/scripts/sqlserver/db_00008.sql
Normal file
4
core/database/scripts/sqlserver/db_00008.sql
Normal file
|
@ -0,0 +1,4 @@
|
|||
/* Community edition */
|
||||
|
||||
-- Performance indexes
|
||||
CREATE INDEX idx_action_5 ON dmz_action (c_orgid,c_userid,c_docid,c_actiontype,c_iscomplete,c_reftype,c_reftypeid);
|
8
core/database/scripts/sqlserver/db_00009.sql
Normal file
8
core/database/scripts/sqlserver/db_00009.sql
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* Community edition */
|
||||
|
||||
-- Performance indexes
|
||||
CREATE INDEX idx_action_6 ON dmz_action (c_orgid,c_reftypeid,c_reftype);
|
||||
|
||||
CREATE INDEX idx_action_7 ON dmz_action (c_orgid,c_refid);
|
||||
|
||||
CREATE INDEX idx_section_5 ON dmz_section (c_orgid,c_refid);
|
6
core/database/scripts/sqlserver/db_00010.sql
Normal file
6
core/database/scripts/sqlserver/db_00010.sql
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* Community edition */
|
||||
|
||||
-- Performance indexes
|
||||
CREATE INDEX idx_action_8 ON dmz_action (c_orgid,c_docid);
|
||||
|
||||
CREATE INDEX idx_user_3 ON dmz_user (c_refid);
|
2
core/env/parser.go
vendored
2
core/env/parser.go
vendored
|
@ -129,7 +129,7 @@ func commandLineEnv() (f Flags, ok bool) {
|
|||
f.ConfigSource = "flags/environment"
|
||||
|
||||
if len(f.TLSVersion) == 0 {
|
||||
f.TLSVersion = "1.2"
|
||||
f.TLSVersion = "1.3"
|
||||
}
|
||||
|
||||
return f, ok
|
||||
|
|
|
@ -23,6 +23,10 @@ func SupportedLocales() (locales []string) {
|
|||
locales = append(locales, "de-DE")
|
||||
locales = append(locales, "zh-CN")
|
||||
locales = append(locales, "pt-BR")
|
||||
locales = append(locales, "fr-FR")
|
||||
locales = append(locales, "ja-JP")
|
||||
locales = append(locales, "it-IT")
|
||||
locales = append(locales, "es-AR")
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ package activity
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/documize/community/domain"
|
||||
|
@ -77,8 +76,10 @@ func (s Store) GetDocumentActivity(ctx domain.RequestContext, id string) (a []ac
|
|||
|
||||
// DeleteDocumentChangeActivity removes all entries for document changes (add, remove, update).
|
||||
func (s Store) DeleteDocumentChangeActivity(ctx domain.RequestContext, documentID string) (rows int64, err error) {
|
||||
rows, err = s.DeleteWhere(ctx.Transaction,
|
||||
fmt.Sprintf("DELETE FROM dmz_user_activity WHERE c_orgid='%s' AND c_docid='%s' AND (c_activitytype=1 OR c_activitytype=2 OR c_activitytype=3 OR c_activitytype=4 OR c_activitytype=7)", ctx.OrgID, documentID))
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_user_activity WHERE c_orgid=? AND c_docid=? AND (c_activitytype=1 OR c_activitytype=2 OR c_activitytype=3 OR c_activitytype=4 OR c_activitytype=7)"), ctx.OrgID, documentID)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ package attachment
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -147,8 +146,10 @@ func (s Store) Delete(ctx domain.RequestContext, id string) (rows int64, err err
|
|||
|
||||
// DeleteSection removes all attachments agasinst a section.
|
||||
func (s Store) DeleteSection(ctx domain.RequestContext, sectionID string) (rows int64, err error) {
|
||||
rows, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_doc_attachment WHERE c_orgid='%s' AND c_sectionid='%s'",
|
||||
ctx.OrgID, sectionID))
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_doc_attachment WHERE c_orgid=? AND c_sectionid=?"), ctx.OrgID, sectionID)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -176,46 +176,69 @@ func (s Store) AssociateDocument(ctx domain.RequestContext, m category.Member) (
|
|||
|
||||
// DisassociateDocument removes document associatation from category.
|
||||
func (s Store) DisassociateDocument(ctx domain.RequestContext, categoryID, documentID string) (rows int64, err error) {
|
||||
sql := fmt.Sprintf("DELETE FROM dmz_category_member WHERE c_orgid='%s' AND c_categoryid='%s' AND c_docid='%s'",
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_category_member WHERE c_orgid=? AND c_categoryid=? AND c_docid=?"),
|
||||
ctx.OrgID, categoryID, documentID)
|
||||
|
||||
return s.DeleteWhere(ctx.Transaction, sql)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// RemoveCategoryMembership removes all category associations from the store.
|
||||
func (s Store) RemoveCategoryMembership(ctx domain.RequestContext, categoryID string) (rows int64, err error) {
|
||||
sql := fmt.Sprintf("DELETE FROM dmz_category_member WHERE c_orgid='%s' AND c_categoryid='%s'",
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_category_member WHERE c_orgid=? AND c_categoryid=?"),
|
||||
ctx.OrgID, categoryID)
|
||||
|
||||
return s.DeleteWhere(ctx.Transaction, sql)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// RemoveSpaceCategoryMemberships removes all category associations from the store for the space.
|
||||
func (s Store) RemoveSpaceCategoryMemberships(ctx domain.RequestContext, spaceID string) (rows int64, err error) {
|
||||
sql := fmt.Sprintf("DELETE FROM dmz_category_member WHERE c_orgid='%s' AND c_spaceid='%s'",
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_category_member WHERE c_orgid=? AND c_spaceid=?"),
|
||||
ctx.OrgID, spaceID)
|
||||
|
||||
return s.DeleteWhere(ctx.Transaction, sql)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// RemoveDocumentCategories removes all document category associations from the store.
|
||||
func (s Store) RemoveDocumentCategories(ctx domain.RequestContext, documentID string) (rows int64, err error) {
|
||||
sql := fmt.Sprintf("DELETE FROM dmz_category_member WHERE c_orgid='%s' AND c_docid='%s'",
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_category_member WHERE c_orgid=? AND c_docid=?"),
|
||||
ctx.OrgID, documentID)
|
||||
|
||||
return s.DeleteWhere(ctx.Transaction, sql)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteBySpace removes all category and category associations for given space.
|
||||
func (s Store) DeleteBySpace(ctx domain.RequestContext, spaceID string) (rows int64, err error) {
|
||||
s1 := fmt.Sprintf("DELETE FROM dmz_category_member WHERE c_orgid='%s' AND c_spaceid='%s'", ctx.OrgID, spaceID)
|
||||
_, err = s.DeleteWhere(ctx.Transaction, s1)
|
||||
if err != nil {
|
||||
return
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_category_member WHERE c_orgid=? AND c_spaceid=?"),
|
||||
ctx.OrgID, spaceID)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
||||
s2 := fmt.Sprintf("DELETE FROM dmz_category WHERE c_orgid='%s' AND c_spaceid='%s'", ctx.OrgID, spaceID)
|
||||
return s.DeleteWhere(ctx.Transaction, s2)
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_category WHERE c_orgid=? AND c_spaceid=?"),
|
||||
ctx.OrgID, spaceID)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetSpaceCategorySummary returns number of documents and users for space categories.
|
||||
|
|
|
@ -64,6 +64,13 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
var ok bool
|
||||
ctx.Transaction, ok = h.Runtime.StartTx(sql.LevelReadUncommitted)
|
||||
if !ok {
|
||||
h.Runtime.Log.Info("unable to start transaction " + method)
|
||||
return
|
||||
}
|
||||
|
||||
document, err := h.Store.Document.Get(ctx, id)
|
||||
if err == sql.ErrNoRows {
|
||||
response.WriteNotFoundError(w, method, id)
|
||||
|
@ -82,7 +89,6 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// draft mode does not record document views
|
||||
if document.Lifecycle == workflow.LifecycleLive {
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
|
@ -95,9 +101,10 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
|
|||
SourceType: activity.SourceTypeDocument,
|
||||
ActivityType: activity.TypeRead})
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
}
|
||||
|
||||
ctx.Transaction.Commit()
|
||||
|
||||
h.Store.Audit.Record(ctx, audit.EventTypeDocumentView)
|
||||
|
||||
response.WriteJSON(w, document)
|
||||
|
@ -360,6 +367,13 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
var ok bool
|
||||
ctx.Transaction, ok = h.Runtime.StartTx(sql.LevelReadUncommitted)
|
||||
if !ok {
|
||||
h.Runtime.Log.Info("unable to start transaction " + method)
|
||||
return
|
||||
}
|
||||
|
||||
doc, err := h.Store.Document.Get(ctx, documentID)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
|
@ -396,13 +410,6 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = h.Store.Document.Delete(ctx, documentID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
|
@ -560,6 +567,13 @@ func (h *Handler) FetchDocumentData(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
var ok bool
|
||||
ctx.Transaction, ok = h.Runtime.StartTx(sql.LevelReadUncommitted)
|
||||
if !ok {
|
||||
h.Runtime.Log.Info("unable to start transaction " + method)
|
||||
return
|
||||
}
|
||||
|
||||
document, err := h.Store.Document.Get(ctx, id)
|
||||
if err == sql.ErrNoRows {
|
||||
response.WriteNotFoundError(w, method, id)
|
||||
|
@ -667,23 +681,22 @@ func (h *Handler) FetchDocumentData(w http.ResponseWriter, r *http.Request) {
|
|||
// Get version information for this document.
|
||||
v := []doc.Version{}
|
||||
if len(document.GroupID) > 0 {
|
||||
// Get versions.
|
||||
// Get versions
|
||||
vt, err := h.Store.Document.GetVersions(ctx, document.GroupID)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
// What about draft document versions?
|
||||
if record.DocumentLifecycle {
|
||||
// We can see and manage document lifecycle so take all versions.
|
||||
v = vt
|
||||
} else {
|
||||
// Only send back LIVE content because user cannot drafts.
|
||||
for i := range vt {
|
||||
if vt[i].Lifecycle == workflow.LifecycleLive {
|
||||
v = append(v, vt[i])
|
||||
}
|
||||
// Determine which document versions user can see.
|
||||
for i := range vt {
|
||||
// Everyone can see live documents
|
||||
if vt[i].Lifecycle == workflow.LifecycleLive {
|
||||
v = append(v, vt[i])
|
||||
}
|
||||
// Only lifecycle admins can see draft documents
|
||||
if vt[i].Lifecycle == workflow.LifecycleDraft && record.DocumentLifecycle {
|
||||
v = append(v, vt[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -709,13 +722,6 @@ func (h *Handler) FetchDocumentData(w http.ResponseWriter, r *http.Request) {
|
|||
data.Versions = v
|
||||
data.Attachments = a
|
||||
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
if document.Lifecycle == workflow.LifecycleLive {
|
||||
h.Store.Activity.RecordUserActivity(ctx, activity.UserActivity{
|
||||
SpaceID: document.SpaceID,
|
||||
|
@ -824,10 +830,10 @@ func (h *Handler) Duplicate(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
ctx.Transaction, err = h.Runtime.Db.Beginx()
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
var ok bool
|
||||
ctx.Transaction, ok = h.Runtime.StartTx(sql.LevelReadUncommitted)
|
||||
if !ok {
|
||||
h.Runtime.Log.Info("unable to start transaction " + method)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -254,31 +254,11 @@ func (s Store) MoveActivity(ctx domain.RequestContext, documentID, oldSpaceID, n
|
|||
// Delete removes the specified document.
|
||||
// Remove document pages, revisions, attachments, updates the search subsystem.
|
||||
func (s Store) Delete(ctx domain.RequestContext, documentID string) (rows int64, err error) {
|
||||
rows, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_section WHERE c_docid='%s' AND c_orgid='%s'", documentID, ctx.OrgID))
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_section_revision WHERE c_docid='%s' AND c_orgid='%s'", documentID, ctx.OrgID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_doc_attachment WHERE c_docid='%s' AND c_orgid='%s'", documentID, ctx.OrgID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_category_member WHERE c_docid='%s' AND c_orgid='%s'", documentID, ctx.OrgID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_doc_vote WHERE c_docid='%s' AND c_orgid='%s'", documentID, ctx.OrgID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_section WHERE c_orgid=? AND c_docid=?"), ctx.OrgID, documentID)
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_section_revision WHERE c_orgid=? AND c_docid=?"), ctx.OrgID, documentID)
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_doc_attachment WHERE c_orgid=? AND c_docid=?"), ctx.OrgID, documentID)
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_category_member WHERE c_orgid=? AND c_docid=?"), ctx.OrgID, documentID)
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_doc_vote WHERE c_orgid=? AND c_docid=?"), ctx.OrgID, documentID)
|
||||
|
||||
return s.DeleteConstrained(ctx.Transaction, "dmz_doc", ctx.OrgID, documentID)
|
||||
}
|
||||
|
@ -286,25 +266,10 @@ func (s Store) Delete(ctx domain.RequestContext, documentID string) (rows int64,
|
|||
// DeleteBySpace removes all documents for given space.
|
||||
// Remove document pages, revisions, attachments, updates the search subsystem.
|
||||
func (s Store) DeleteBySpace(ctx domain.RequestContext, spaceID string) (rows int64, err error) {
|
||||
rows, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_section WHERE c_docid IN (SELECT c_refid FROM dmz_doc WHERE c_spaceid='%s' AND c_orgid='%s')", spaceID, ctx.OrgID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_section_revision WHERE c_docid IN (SELECT c_refid FROM dmz_doc WHERE c_spaceid='%s' AND c_orgid='%s')", spaceID, ctx.OrgID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_doc_attachment WHERE c_docid IN (SELECT c_refid FROM dmz_doc WHERE c_spaceid='%s' AND c_orgid='%s')", spaceID, ctx.OrgID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_doc_vote WHERE c_docid IN (SELECT c_refid FROM dmz_doc WHERE c_spaceid='%s' AND c_orgid='%s')", spaceID, ctx.OrgID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_section WHERE c_docid IN (SELECT c_refid FROM dmz_doc WHERE c_spaceid=? AND c_orgid=?)"), spaceID, ctx.OrgID)
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_section_revision WHERE c_docid IN (SELECT c_refid FROM dmz_doc WHERE c_spaceid=? AND c_orgid=?)"), spaceID, ctx.OrgID)
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_doc_attachment WHERE c_docid IN (SELECT c_refid FROM dmz_doc WHERE c_spaceid=? AND c_orgid=?)"), spaceID, ctx.OrgID)
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_doc_vote WHERE c_docid IN (SELECT c_refid FROM dmz_doc WHERE c_spaceid=? AND c_orgid=?)"), spaceID, ctx.OrgID)
|
||||
|
||||
return s.DeleteConstrained(ctx.Transaction, "dmz_doc", ctx.OrgID, spaceID)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ package group
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/documize/community/domain"
|
||||
|
@ -104,7 +103,10 @@ func (s Store) Delete(ctx domain.RequestContext, refID string) (rows int64, err
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
return s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_group_member WHERE c_orgid='%s' AND c_groupid='%s'", ctx.OrgID, refID))
|
||||
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_group_member WHERE c_orgid=? AND c_groupid=?"), ctx.OrgID, refID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetGroupMembers returns all user associated with given group.
|
||||
|
@ -143,15 +145,8 @@ func (s Store) JoinGroup(ctx domain.RequestContext, groupID, userID string) (err
|
|||
|
||||
// LeaveGroup removes user from group.
|
||||
func (s Store) LeaveGroup(ctx domain.RequestContext, groupID, userID string) (err error) {
|
||||
_, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_group_member WHERE c_orgid='%s' AND c_groupid='%s' AND c_userid='%s'",
|
||||
ctx.OrgID, groupID, userID))
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "clear group member")
|
||||
}
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_group_member WHERE c_orgid=? AND c_groupid=? AND c_userid=?"),
|
||||
ctx.OrgID, groupID, userID)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -182,16 +177,8 @@ func (s Store) GetMembers(ctx domain.RequestContext) (r []group.Record, err erro
|
|||
|
||||
// RemoveUserGroups remove user from all group.
|
||||
func (s Store) RemoveUserGroups(ctx domain.RequestContext, userID string) (err error) {
|
||||
_, err = s.DeleteWhere(ctx.Transaction,
|
||||
fmt.Sprintf("DELETE FROM dmz_group_member WHERE c_orgid='%s' AND c_userid='%s'",
|
||||
ctx.OrgID, userID))
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "RemoveUserGroups")
|
||||
}
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_group_member WHERE c_orgid=? AND c_userid=?"),
|
||||
ctx.OrgID, userID)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ package link
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -156,12 +155,18 @@ func (s Store) MarkOrphanAttachmentLink(ctx domain.RequestContext, attachmentID
|
|||
|
||||
// DeleteSourcePageLinks removes saved links for given source.
|
||||
func (s Store) DeleteSourcePageLinks(ctx domain.RequestContext, pageID string) (rows int64, err error) {
|
||||
return s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_doc_link WHERE c_orgid='%s' AND c_sourcesectionid='%s'", ctx.OrgID, pageID))
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_doc_link WHERE c_orgid=? AND c_sourcesectionid=?"),
|
||||
ctx.OrgID, pageID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteSourceDocumentLinks removes saved links for given document.
|
||||
func (s Store) DeleteSourceDocumentLinks(ctx domain.RequestContext, documentID string) (rows int64, err error) {
|
||||
return s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_doc_link WHERE c_orgid='%s' AND c_sourcedocid='%s'", ctx.OrgID, documentID))
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_doc_link WHERE c_orgid=? AND c_sourcedocid=?"),
|
||||
ctx.OrgID, documentID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteLink removes saved link from the store.
|
||||
|
|
|
@ -201,13 +201,12 @@ func (s Store) Update(ctx domain.RequestContext, page page.Page, refID, userID s
|
|||
// It then propagates that change into the search table, adds a delete the page revisions history, and audits that the page has been removed.
|
||||
func (s Store) Delete(ctx domain.RequestContext, documentID, pageID string) (rows int64, err error) {
|
||||
rows, err = s.DeleteConstrained(ctx.Transaction, "dmz_section", ctx.OrgID, pageID)
|
||||
if err == nil {
|
||||
_, _ = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_section_meta WHERE c_orgid='%s' AND c_sectionid='%s'", ctx.OrgID, pageID))
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
_, _ = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_action WHERE c_orgid='%s' AND c_reftypeid='%s' AND c_reftype='P'", ctx.OrgID, pageID))
|
||||
}
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_section_meta WHERE c_orgid=? AND c_sectionid=?"),
|
||||
ctx.OrgID, pageID)
|
||||
|
||||
ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_action WHERE c_orgid=? AND c_reftypeid=? AND c_reftype='P'"),
|
||||
ctx.OrgID, pageID)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -408,8 +407,8 @@ func (s Store) GetDocumentRevisions(ctx domain.RequestContext, documentID string
|
|||
|
||||
// DeletePageRevisions deletes all of the page revision records for a given pageID.
|
||||
func (s Store) DeletePageRevisions(ctx domain.RequestContext, pageID string) (rows int64, err error) {
|
||||
rows, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_section_revision WHERE c_orgid='%s' AND c_sectionid='%s'",
|
||||
ctx.OrgID, pageID))
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_section_revision WHERE c_orgid=? AND c_sectionid=?"),
|
||||
ctx.OrgID, pageID)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ func CanViewDocument(ctx domain.RequestContext, s store.Store, documentID string
|
|||
return false
|
||||
}
|
||||
|
||||
// CanChangeDocument returns if the clinet has permission to change a given document.
|
||||
// CanChangeDocument returns if the client has permission to change a given document.
|
||||
func CanChangeDocument(ctx domain.RequestContext, s store.Store, documentID string) bool {
|
||||
document, err := s.Document.Get(ctx, documentID)
|
||||
|
||||
|
@ -98,7 +98,7 @@ func CanChangeDocument(ctx domain.RequestContext, s store.Store, documentID stri
|
|||
return false
|
||||
}
|
||||
|
||||
// CanDeleteDocument returns if the clinet has permission to change a given document.
|
||||
// CanDeleteDocument returns if the client has permission to change a given document.
|
||||
func CanDeleteDocument(ctx domain.RequestContext, s store.Store, documentID string) bool {
|
||||
document, err := s.Document.Get(ctx, documentID)
|
||||
|
||||
|
@ -166,7 +166,6 @@ func CanManageSpace(ctx domain.RequestContext, s store.Store, spaceID string) bo
|
|||
return false
|
||||
}
|
||||
|
||||
|
||||
// CanViewSpace returns if the user has permission to view the given spaceID.
|
||||
func CanViewSpace(ctx domain.RequestContext, s store.Store, spaceID string) bool {
|
||||
roles, err := s.Permission.GetUserSpacePermissions(ctx, spaceID)
|
||||
|
|
|
@ -266,55 +266,56 @@ func (s Store) GetDocumentPermissions(ctx domain.RequestContext, documentID stri
|
|||
|
||||
// DeleteDocumentPermissions removes records from dmz_permissions table for given document.
|
||||
func (s Store) DeleteDocumentPermissions(ctx domain.RequestContext, documentID string) (rows int64, err error) {
|
||||
sql := fmt.Sprintf("DELETE FROM dmz_permission WHERE c_orgid='%s' AND c_location='document' AND c_refid='%s'", ctx.OrgID, documentID)
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_permission WHERE c_orgid=? AND c_location='document' AND c_refid=?"),
|
||||
ctx.OrgID, documentID)
|
||||
|
||||
return s.DeleteWhere(ctx.Transaction, sql)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteSpacePermissions removes records from dmz_permissions table for given space ID.
|
||||
func (s Store) DeleteSpacePermissions(ctx domain.RequestContext, spaceID string) (rows int64, err error) {
|
||||
sql := fmt.Sprintf("DELETE FROM dmz_permission WHERE c_orgid='%s' AND c_location='space' AND c_refid='%s'", ctx.OrgID, spaceID)
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_permission WHERE c_orgid=? AND c_location='space' AND c_refid=?"),
|
||||
ctx.OrgID, spaceID)
|
||||
|
||||
return s.DeleteWhere(ctx.Transaction, sql)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteUserSpacePermissions removes all roles for the specified user, for the specified space.
|
||||
func (s Store) DeleteUserSpacePermissions(ctx domain.RequestContext, spaceID, userID string) (rows int64, err error) {
|
||||
sql := fmt.Sprintf("DELETE FROM dmz_permission WHERE c_orgid='%s' AND c_location='space' AND c_refid='%s' AND c_who='user' AND c_whoid='%s'",
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_permission WHERE c_orgid=? AND c_location='space' AND c_refid=? AND c_who='user' AND c_whoid=?"),
|
||||
ctx.OrgID, spaceID, userID)
|
||||
|
||||
return s.DeleteWhere(ctx.Transaction, sql)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteUserPermissions removes all roles for the specified user, for the specified space.
|
||||
func (s Store) DeleteUserPermissions(ctx domain.RequestContext, userID string) (rows int64, err error) {
|
||||
sql := fmt.Sprintf("DELETE FROM dmz_permission WHERE c_orgid='%s' AND c_who='user' AND c_whoid='%s'",
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_permission WHERE c_orgid=? AND c_who='user' AND c_whoid=?"),
|
||||
ctx.OrgID, userID)
|
||||
|
||||
return s.DeleteWhere(ctx.Transaction, sql)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteCategoryPermissions removes records from dmz_permissions table for given category ID.
|
||||
func (s Store) DeleteCategoryPermissions(ctx domain.RequestContext, categoryID string) (rows int64, err error) {
|
||||
sql := fmt.Sprintf("DELETE FROM dmz_permission WHERE c_orgid='%s' AND c_location='category' AND c_refid='%s'", ctx.OrgID, categoryID)
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_permission WHERE c_orgid=? AND c_location='category' AND c_refid=?"),
|
||||
ctx.OrgID, categoryID)
|
||||
|
||||
return s.DeleteWhere(ctx.Transaction, sql)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteSpaceCategoryPermissions removes all category permission for for given space.
|
||||
func (s Store) DeleteSpaceCategoryPermissions(ctx domain.RequestContext, spaceID string) (rows int64, err error) {
|
||||
sql := fmt.Sprintf(`
|
||||
DELETE FROM dmz_permission WHERE c_orgid='%s' AND c_location='category'
|
||||
AND c_refid IN (SELECT c_refid FROM dmz_category WHERE c_orgid='%s' AND c_spaceid='%s')`,
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_permission WHERE c_orgid=? AND c_location='category' AND c_refid IN (SELECT c_refid FROM dmz_category WHERE c_orgid=? AND c_spaceid=?)"),
|
||||
ctx.OrgID, ctx.OrgID, spaceID)
|
||||
|
||||
return s.DeleteWhere(ctx.Transaction, sql)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteGroupPermissions removes all roles for the specified group
|
||||
func (s Store) DeleteGroupPermissions(ctx domain.RequestContext, groupID string) (rows int64, err error) {
|
||||
sql := fmt.Sprintf("DELETE FROM dmz_permission WHERE c_orgid='%s' AND c_who='role' AND c_whoid='%s'",
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_permission WHERE c_orgid=? AND c_who='role' AND c_whoid=?"),
|
||||
ctx.OrgID, groupID)
|
||||
|
||||
return s.DeleteWhere(ctx.Transaction, sql)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -120,10 +120,16 @@ func (s Store) DeletePin(ctx domain.RequestContext, id string) (rows int64, err
|
|||
|
||||
// DeletePinnedSpace removes any pins for specified space.
|
||||
func (s Store) DeletePinnedSpace(ctx domain.RequestContext, spaceID string) (rows int64, err error) {
|
||||
return s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_pin WHERE c_orgid='%s' AND c_spaceid='%s'", ctx.OrgID, spaceID))
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_pin WHERE c_orgid=? AND c_spaceid=?"),
|
||||
ctx.OrgID, spaceID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeletePinnedDocument removes any pins for specified document.
|
||||
func (s Store) DeletePinnedDocument(ctx domain.RequestContext, documentID string) (rows int64, err error) {
|
||||
return s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_pin WHERE c_orgid='%s' AND c_docid='%s'", ctx.OrgID, documentID))
|
||||
_, err = ctx.Transaction.Exec(s.Bind("DELETE FROM dmz_pin WHERE c_orgid=? AND c_docid=?"),
|
||||
ctx.OrgID, documentID)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ type Context struct {
|
|||
|
||||
// Bind selects query parameter placeholder for given database provider.
|
||||
//
|
||||
// MySQL uses ?, ?, ? (default for all Documize queries).``
|
||||
// MySQL uses ?, ?, ? (default for all Documize queries).“
|
||||
// PostgreSQL uses $1, $2, $3.
|
||||
// MS SQL Server uses @p1, @p2, @p3.
|
||||
func (c *Context) Bind(sql string) string {
|
||||
|
@ -86,20 +86,6 @@ func (c *Context) DeleteConstrainedWithID(tx *sqlx.Tx, table string, orgID, id s
|
|||
return
|
||||
}
|
||||
|
||||
// DeleteWhere free form query.
|
||||
func (c *Context) DeleteWhere(tx *sqlx.Tx, statement string) (rows int64, err error) {
|
||||
_, err = tx.Exec(statement)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, fmt.Sprintf("unable to delete rows: %s", statement))
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// EmptyJSON returns database specific empty JSON object.
|
||||
func (c *Context) EmptyJSON() string {
|
||||
return c.Runtime.StoreProvider.JSONEmpty()
|
||||
|
|
|
@ -508,6 +508,21 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// Trap for non-admin users boosting their own user roles
|
||||
if u.Admin && !a.Admin && !ctx.Administrator {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
if u.Editor && !a.Editor && !ctx.Administrator {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
if u.Active && !a.Active && !ctx.Administrator {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
}
|
||||
|
||||
// Set user roles
|
||||
a.Editor = u.Editor
|
||||
a.Admin = u.Admin
|
||||
a.Active = u.Active
|
||||
|
|
|
@ -40,9 +40,9 @@ func main() {
|
|||
// Specify the product edition.
|
||||
rt.Product = domain.Product{}
|
||||
rt.Product.Major = "5"
|
||||
rt.Product.Minor = "4"
|
||||
rt.Product.Patch = "2"
|
||||
rt.Product.Revision = "221021105923"
|
||||
rt.Product.Minor = "13"
|
||||
rt.Product.Patch = "0"
|
||||
rt.Product.Revision = "1735665467719"
|
||||
rt.Product.Version = fmt.Sprintf("%s.%s.%s", rt.Product.Major, rt.Product.Minor, rt.Product.Patch)
|
||||
rt.Product.Edition = domain.CommunityEdition
|
||||
rt.Product.Title = "Community"
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
_ "github.com/denisenkom/go-mssqldb" // the SQL Server driver is required behind the scenes
|
||||
"github.com/documize/community/core/env"
|
||||
account "github.com/documize/community/domain/account"
|
||||
activity "github.com/documize/community/domain/activity"
|
||||
|
@ -39,6 +38,7 @@ import (
|
|||
space "github.com/documize/community/domain/space"
|
||||
"github.com/documize/community/domain/store"
|
||||
user "github.com/documize/community/domain/user"
|
||||
_ "github.com/microsoft/go-mssqldb" // the SQL Server driver is required behind the scenes
|
||||
)
|
||||
|
||||
// SQLServerProvider supports Microsoft SQl Server.
|
||||
|
@ -55,12 +55,17 @@ type SQLServerProvider struct {
|
|||
// Useful links:
|
||||
//
|
||||
// Driver for Golang:
|
||||
// https://github.com/denisenkom/go-mssqldb
|
||||
//
|
||||
// https://github.com/denisenkom/go-mssqldb
|
||||
//
|
||||
// Docker Linux testing:
|
||||
// https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-2017
|
||||
// docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Passw0rd' -p 1433:1433 --name sql1 -d mcr.microsoft.com/mssql/server:2017-latest
|
||||
//
|
||||
// https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-2017
|
||||
// docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Passw0rd' -p 1433:1433 --name sql1 -d mcr.microsoft.com/mssql/server:2017-latest
|
||||
//
|
||||
// JSON types:
|
||||
// https://docs.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server?view=sql-server-2017
|
||||
//
|
||||
// https://docs.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server?view=sql-server-2017
|
||||
//
|
||||
// Supports 2016, 2017 and 2019.
|
||||
func SetSQLServerProvider(r *env.Runtime, s *store.Store) {
|
||||
|
@ -271,7 +276,7 @@ func (p SQLServerProvider) MakeConnectionString() string {
|
|||
// character set and collation from database provider.
|
||||
func (p SQLServerProvider) QueryMeta() string {
|
||||
return fmt.Sprintf(`
|
||||
SELECT
|
||||
SELECT
|
||||
CAST(SERVERPROPERTY('productversion') AS VARCHAR) AS version,
|
||||
@@VERSION AS comment,
|
||||
collation_name AS collation,
|
||||
|
@ -309,7 +314,7 @@ func (p SQLServerProvider) QueryGetDatabaseVersionLegacy() string {
|
|||
|
||||
// QueryTableList returns a list tables in Documize database.
|
||||
func (p SQLServerProvider) QueryTableList() string {
|
||||
return fmt.Sprintf(`SELECT TABLE_NAME
|
||||
return fmt.Sprintf(`SELECT TABLE_NAME
|
||||
FROM %s.INFORMATION_SCHEMA.TABLES`, p.DatabaseName())
|
||||
}
|
||||
|
||||
|
@ -341,13 +346,17 @@ func (p SQLServerProvider) JSONGetValue(column, attribute string) string {
|
|||
// See: http://sqlserverbuilds.blogspot.com
|
||||
func (p SQLServerProvider) VerfiyVersion(dbVersion string) (bool, string) {
|
||||
|
||||
if strings.HasPrefix(dbVersion, "13.") ||
|
||||
if strings.HasPrefix(dbVersion, "12.") ||
|
||||
strings.HasPrefix(dbVersion, "13.") ||
|
||||
strings.HasPrefix(dbVersion, "14.") ||
|
||||
strings.HasPrefix(dbVersion, "15.") {
|
||||
strings.HasPrefix(dbVersion, "15.") ||
|
||||
strings.HasPrefix(dbVersion, "16.") {
|
||||
return true, ""
|
||||
}
|
||||
|
||||
return false, "Microsoft SQL Server 2016, 2017 or 2019 is required"
|
||||
return true, ""
|
||||
|
||||
// return false, "Microsoft SQL Server 2016+ or SQL Azure is required"
|
||||
}
|
||||
|
||||
// VerfiyCharacterCollation needs to ensure utf8.
|
||||
|
|
56
go.mod
56
go.mod
|
@ -1,47 +1,51 @@
|
|||
module github.com/documize/community
|
||||
|
||||
go 1.19
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/andygrunwald/go-jira v1.12.0
|
||||
github.com/BurntSushi/toml v1.3.2
|
||||
github.com/andygrunwald/go-jira v1.16.0
|
||||
github.com/codegangsta/negroni v1.0.0
|
||||
github.com/denisenkom/go-mssqldb v0.10.1-0.20210728001037-ee2fbc25fd8f
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/documize/blackfriday v2.0.0+incompatible
|
||||
github.com/documize/glick v0.0.0-20160503134043-a8ccbef88237
|
||||
github.com/documize/html-diff v0.0.0-20160503140253-f61c192c7796
|
||||
github.com/documize/slug v1.1.1
|
||||
github.com/go-ldap/ldap/v3 v3.4.1
|
||||
github.com/go-sql-driver/mysql v1.6.0
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
|
||||
github.com/google/go-querystring v1.0.0 // indirect
|
||||
github.com/gorilla/handlers v1.4.2
|
||||
github.com/gorilla/mux v1.7.4
|
||||
github.com/jmoiron/sqlx v1.2.0
|
||||
github.com/kr/pretty v0.2.0 // indirect
|
||||
github.com/lib/pq v1.10.2
|
||||
github.com/go-ldap/ldap/v3 v3.4.6
|
||||
github.com/go-sql-driver/mysql v1.7.1
|
||||
github.com/golang/glog v1.2.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.2
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/jmoiron/sqlx v1.3.5
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/mb0/diff v0.0.0-20131118162322-d8d9a906c24d // indirect
|
||||
github.com/microcosm-cc/bluemonday v1.0.17
|
||||
github.com/microcosm-cc/bluemonday v1.0.26
|
||||
github.com/microsoft/go-mssqldb v1.6.0
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
|
||||
golang.org/x/crypto v0.19.0
|
||||
golang.org/x/net v0.21.0
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc
|
||||
gopkg.in/cas.v2 v2.1.0
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.2 // indirect
|
||||
gopkg.in/cas.v2 v2.2.2
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/fatih/structs v1.0.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
||||
github.com/google/go-cmp v0.4.0 // indirect
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
github.com/trivago/tgo v1.0.1 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
github.com/trivago/tgo v1.0.7 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
)
|
||||
|
|
206
go.sum
206
go.sum
|
@ -1,15 +1,31 @@
|
|||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/andygrunwald/go-jira v1.12.0 h1:JJi2cEDmDxVtTXxC8ruLDbtOU6pA4OLeL0niyfNcoWw=
|
||||
github.com/andygrunwald/go-jira v1.12.0/go.mod h1:jYi4kFDbRPZTJdJOVJO4mpMMIwdB+rcZwSO58DzPd2I=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 h1:/iHxaJhsFr0+xVFfbMr5vxz848jyiWuIEDhYq3y5odY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0 h1:yfJe15aSwEQ6Oo6J+gdfdulPNoZ3TEhmbhLIoxZcA+U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0/go.mod h1:Q28U+75mpCaSCDowNEmhIo/rmgdkqmkmzI7N6TGR4UY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0 h1:HCc0+LpPfpCKs6LGGLAhwBARt9632unrVcI6i8s/8os=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||
github.com/andygrunwald/go-jira v1.16.0 h1:PU7C7Fkk5L96JvPc6vDVIrd99vdPnYudHu4ju2c2ikQ=
|
||||
github.com/andygrunwald/go-jira v1.16.0/go.mod h1:UQH4IBVxIYWbgagc0LF/k9FRs9xjIiQ8hIcC6HfLwFU=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY=
|
||||
github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=
|
||||
github.com/denisenkom/go-mssqldb v0.10.1-0.20210728001037-ee2fbc25fd8f h1:3UtVZFKTqZwLZi65UbfSIqYR75aUTP8FYUAEQnMXSJs=
|
||||
github.com/denisenkom/go-mssqldb v0.10.1-0.20210728001037-ee2fbc25fd8f/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/documize/blackfriday v2.0.0+incompatible h1:qjRGAIVwZlHBtA/b9u0LtseYM3v3WpIXofPCwNjcUsE=
|
||||
|
@ -20,82 +36,148 @@ github.com/documize/html-diff v0.0.0-20160503140253-f61c192c7796 h1:CuipXymSP8Di
|
|||
github.com/documize/html-diff v0.0.0-20160503140253-f61c192c7796/go.mod h1:GTEVMy1JkyV+k/j8hLGRGHVs/IHJS4s7AtJJ9LSYjRQ=
|
||||
github.com/documize/slug v1.1.1 h1:OCJRbWxbOgrgiBYSbVzuFwxb9wVu4oy1LxvLJOC2s8Y=
|
||||
github.com/documize/slug v1.1.1/go.mod h1:Vi7fQ5PzeOpXAiIrk1WCEDRihjTfU/bf4eWUPSD7tkU=
|
||||
github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU=
|
||||
github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3 h1:u7utq56RUFiynqUzgVMFDymapcOtQ/MZkh3H4QYkxag=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-ldap/ldap/v3 v3.4.1 h1:fU/0xli6HY02ocbMuozHAYsaHLcnkLjvho2r5a34BUU=
|
||||
github.com/go-ldap/ldap/v3 v3.4.1/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A=
|
||||
github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
|
||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
|
||||
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
||||
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
|
||||
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
||||
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
|
||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mb0/diff v0.0.0-20131118162322-d8d9a906c24d h1:eAS2t2Vy+6psf9LZ4T5WXWsbkBt3Tu5PWekJy5AGyEU=
|
||||
github.com/mb0/diff v0.0.0-20131118162322-d8d9a906c24d/go.mod h1:3YMHqrw2Qu3Liy82v4QdAG17e9k91HZ7w3hqlpWqhDo=
|
||||
github.com/microcosm-cc/bluemonday v1.0.17 h1:Z1a//hgsQ4yjC+8zEkV8IWySkXnsxmdSY642CTFQb5Y=
|
||||
github.com/microcosm-cc/bluemonday v1.0.17/go.mod h1:Z0r70sCuXHig8YpBzCc5eGHAap2K7e/u082ZUpDRRqM=
|
||||
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
|
||||
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
|
||||
github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc=
|
||||
github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/trivago/tgo v1.0.1 h1:bxatjJIXNIpV18bucU4Uk/LaoxvxuOlp/oowRHyncLQ=
|
||||
github.com/trivago/tgo v1.0.1/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/trivago/tgo v1.0.7 h1:uaWH/XIy9aWYWpjm2CU3RpcqZXmX2ysQ9/Go+d9gyrM=
|
||||
github.com/trivago/tgo v1.0.7/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
gopkg.in/cas.v2 v2.1.0 h1:sbYBMWtpanwLH75GAWjIp5JnON9wa3NodLZhouu0G9I=
|
||||
gopkg.in/cas.v2 v2.1.0/go.mod h1:M291I/o/u3eeMl9SkXMPYpWasHp7weFY9G/pM5DbB+g=
|
||||
gopkg.in/cas.v2 v2.2.2 h1:teLr/JI7VDEQu6qkXKndYac9w5tfy57sWlV+eNYHH+o=
|
||||
gopkg.in/cas.v2 v2.2.2/go.mod h1:mlmjh4qM/Jm3eSDD0QVr5GaaSW3nOonSUSWkLLvNYnI=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
@ -9,7 +9,7 @@ import Service, { inject as service } from '@ember/service';
|
|||
import $ from 'jquery';
|
||||
|
||||
export default Service.extend({
|
||||
langs: { enUS: [], deDE: [] , zhCN: [], ptBR: [] },
|
||||
langs: { enUS: [], deDE: [] , zhCN: [], ptBR: [], frFR: [], jaJP: [], itIT: [], esAR: [] },
|
||||
locales: [],
|
||||
session: service(),
|
||||
|
||||
|
@ -27,6 +27,18 @@ export default Service.extend({
|
|||
$.getJSON("/i18n/pt-BR.json", (data) => {
|
||||
this.langs.ptBR = data;
|
||||
});
|
||||
$.getJSON("/i18n/fr-FR.json", (data) => {
|
||||
this.langs.frFR = data;
|
||||
});
|
||||
$.getJSON("/i18n/ja-JP.json", (data) => {
|
||||
this.langs.jaJP = data;
|
||||
});
|
||||
$.getJSON("/i18n/it-IT.json", (data) => {
|
||||
this.langs.itIT = data;
|
||||
});
|
||||
$.getJSON("/i18n/es-AR.json", (data) => {
|
||||
this.langs.esAR = data;
|
||||
});
|
||||
},
|
||||
|
||||
localize(key, ...args) {
|
||||
|
@ -45,7 +57,19 @@ export default Service.extend({
|
|||
case "pt-BR":
|
||||
str = this.langs.ptBR[key];
|
||||
break;
|
||||
}
|
||||
case "fr-FR":
|
||||
str = this.langs.frFR[key];
|
||||
break;
|
||||
case "ja-JP":
|
||||
str = this.langs.jaJP[key];
|
||||
break;
|
||||
case "it-IT":
|
||||
str = this.langs.itIT[key];
|
||||
break;
|
||||
case "es-AR":
|
||||
str = this.langs.esAR[key];
|
||||
break;
|
||||
}
|
||||
|
||||
if (_.isUndefined(str)) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<label for="conversionEndpoint">{{localize 'customize_conversion_url'}}</label>
|
||||
{{input id="conversionEndpoint" type="text" value=model.general.conversionEndpoint class=(if hasConversionEndpointInputError "form-control is-invalid" "form-control")}}
|
||||
<small class="form-text text-muted">
|
||||
{{localize 'customize_conversion_explain'}} (e.g. https://api.documize.com, <a href="https://docs.documize.com/s/WNEpptWJ9AABRnha/administration-guides/d/WO0pt_MXigAB6sJ7/general-options">read the documentation</a>)
|
||||
{{localize 'customize_conversion_explain'}} (See <a href="https://docs.documize.com/s/WNEpptWJ9AABRnha/administration-guides/d/WO0pt_MXigAB6sJ7/general-options">documentation</a>)
|
||||
</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
<div class="form-group">
|
||||
<label for="activation-key">Activation Key</label>
|
||||
{{textarea id="activation-key" value=model.activationKey rows="5" class=(if hasKeyError "form-control is-invalid" "form-control")}}
|
||||
<small class="form-text text-muted">You can get from <a href="https://www.documize.com/community" target="_blank">https://www.documize.com/community</a></small>
|
||||
<small class="form-text text-muted">Get from here: <a href="https://www.documize.com/community" target="_blank">https://www.documize.com/community</a></small>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{ui/ui-button submit=true color=constants.Color.Green light=true label=buttonLabel onClick=(action "save")}}
|
||||
|
|
5281
gui/package-lock.json
generated
5281
gui/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "documize",
|
||||
"version": "5.4.2",
|
||||
"version": "5.13.0",
|
||||
"private": true,
|
||||
"description": "Documize Community",
|
||||
"repository": "",
|
||||
|
|
758
gui/public/i18n/es-AR.json
Normal file
758
gui/public/i18n/es-AR.json
Normal file
|
@ -0,0 +1,758 @@
|
|||
{
|
||||
"all": "Todos",
|
||||
"none": "Ninguno",
|
||||
"never": "Nunca",
|
||||
"add": "Agregar",
|
||||
"added": "Agregado",
|
||||
"activate": "Activar",
|
||||
"summary": "Resumen",
|
||||
"approve": "Aprobar",
|
||||
"authenticate": "Autenticar",
|
||||
"cancel": "Cancelar",
|
||||
"close": "Cerrar",
|
||||
"copy": "Copiar",
|
||||
"copied": "Copiado",
|
||||
"delete": "Borrar",
|
||||
"deleted": "Eliminado",
|
||||
"remove": "Eliminar",
|
||||
"duplicate": "Duplicado",
|
||||
"duplicated": "Duplicado",
|
||||
"edit": "Editar",
|
||||
"edited": "Editado",
|
||||
"download": "Descargar",
|
||||
"upload": "subir",
|
||||
"uploaded": "Subido",
|
||||
"import": "Importar",
|
||||
"export": "Exportar",
|
||||
"exported": "Exportado",
|
||||
"pdf": "PDF",
|
||||
"test": "Prueba",
|
||||
"configure": "Configurar",
|
||||
"error": "Error",
|
||||
"file": "Archivo",
|
||||
"insert": "Insertar",
|
||||
"invite": "Invitar",
|
||||
"message": "Mensaje",
|
||||
"join": "Unirse",
|
||||
"leave": "Salir",
|
||||
"login": "Iniciar sesión",
|
||||
"logout": "Cerrar sesión",
|
||||
"authentication": "Autenticación",
|
||||
"move": "Mover",
|
||||
"moved": "Movido",
|
||||
"next": "Siguiente",
|
||||
"ok": "Aceptar",
|
||||
"preview": "Vista previa",
|
||||
"preview_wait": "Generando vista previa...",
|
||||
"pdf_prepare": "Preparando PDF...",
|
||||
"publish": "Publicar",
|
||||
"print": "Imprimir",
|
||||
"reject": "Rechazar",
|
||||
"rejected": "Rechazado",
|
||||
"reply": "Responder",
|
||||
"replied": "Respondido",
|
||||
"reset": "Restablecer",
|
||||
"request": "Solicitar",
|
||||
"requested": "Solicitado",
|
||||
"save": "Guardar",
|
||||
"saved": "Guardado",
|
||||
"search": "Buscar",
|
||||
"send": "Enviar",
|
||||
"share": "Compartir",
|
||||
"discard": "Descartar",
|
||||
"continue": "Continuar",
|
||||
"code": "código",
|
||||
"signin": "Iniciar sesión",
|
||||
"sort": "Ordenar",
|
||||
"sort_ascending": "Ascendente",
|
||||
"sort_descending": "Descendente",
|
||||
"sort_by_name": "Nombre",
|
||||
"sort_by_created": "Fecha de creación",
|
||||
"sort_by_revised": "Última actualización",
|
||||
"unassigned": "Sin asignar",
|
||||
"update": "Actualizar",
|
||||
"updating": "Actualizando",
|
||||
"viewed": "Visto",
|
||||
"name": "Nombre",
|
||||
"description": "Descripción",
|
||||
"excerpt": "Extracto",
|
||||
"icon": "Icono",
|
||||
"color": "Color",
|
||||
"visibility": "Visibilidad",
|
||||
"running": "En ejecución...",
|
||||
"firstname": "Nombre",
|
||||
"lastname": "Apellido",
|
||||
"email": "Correo electrónico",
|
||||
"email_recipient": "Correo electrónico del destinatario",
|
||||
"password": "Contraseña",
|
||||
"password_new": "Nueva contraseña",
|
||||
"username": "Nombre de usuario",
|
||||
"user": "Usuario",
|
||||
"password_confirm": "Confirmar contraseña",
|
||||
"encryption": "Cifrado",
|
||||
"notice": "Aviso",
|
||||
"backup": "Copia de seguridad",
|
||||
"restore": "Restaurar",
|
||||
"completed": "Completado",
|
||||
"please_wait": "Por favor, espere...",
|
||||
"filter": "Filtro",
|
||||
"not_found": "No encontrado",
|
||||
"nothing_found": "No se encontró nada",
|
||||
"expand_collapse": "Expandir/contraer",
|
||||
"options": "Opciones",
|
||||
"settings": "Configuración",
|
||||
"about": "Acerca de",
|
||||
"meta": "Meta",
|
||||
"permissions": "Permisos",
|
||||
"profile": "Perfil",
|
||||
"go_top": "Ir al inicio",
|
||||
"help": "Ayuda",
|
||||
"reference": "referencia",
|
||||
"references": "referencias",
|
||||
"move_up": "Subir",
|
||||
"move_down": "Bajar",
|
||||
"indent": "Sangría",
|
||||
"outdent": "Anular sangría",
|
||||
"default": "Predeterminado",
|
||||
"no_undo": "Proceda con precaución, ya que no se puede deshacer",
|
||||
"show_hide": "Mostrar/ocultar",
|
||||
"sent": "Enviado",
|
||||
"everyone": "Todos",
|
||||
"ip": "IP",
|
||||
"event": "Evento",
|
||||
"when": "Cuándo",
|
||||
"last_seen": "Última vez visto",
|
||||
"change": "Cambiar",
|
||||
"no_access": "Acceso denegado",
|
||||
"drag_drop_reorder": "Arrastrar y soltar para reordenar",
|
||||
"select": "Seleccionar",
|
||||
"locale": "Configuración regional",
|
||||
|
||||
"public": "Público",
|
||||
"public_explain": "Público: puede ser visto por todos",
|
||||
"protected": "Protegido",
|
||||
"protected_explain": "Protegido: el acceso está restringido a usuarios seleccionados",
|
||||
"personal": "Personal",
|
||||
"personal_explain": "Personal: solo yo puedo verlo",
|
||||
"label": "Etiqueta",
|
||||
"labels": "Etiquetas",
|
||||
"labels_none": "Sin etiquetas",
|
||||
"label_unclassified": "Sin clasificar",
|
||||
"draft": "Borrador",
|
||||
"drafted": "En borrador",
|
||||
"draft_explain": "Borrador: debe ser aprobado antes de la publicación, sin historial de revisión",
|
||||
"drafts": "Borradores",
|
||||
"live": "En vivo",
|
||||
"live_explain": "En vivo: publicado al crearse",
|
||||
"archived": "Archivado",
|
||||
"archived_explain": "Archivado: no visible para nadie",
|
||||
"approved": "Aprobado",
|
||||
"reverted": "Revertido",
|
||||
"published": "Publicado",
|
||||
"space": "Espacio",
|
||||
"spaces": "Espacios",
|
||||
"category": "Categoría",
|
||||
"category_explain": "Asignar categorías a los documentos y decidir quién puede verlos",
|
||||
"categories": "Categorías",
|
||||
"tag": "Etiqueta",
|
||||
"tags": "Etiquetas",
|
||||
"tag_rules": "Especificar hasta {1} etiquetas: minúsculas, caracteres, números, guiones solamente",
|
||||
"revisions": "Revisiones",
|
||||
"versions": "Versiones",
|
||||
"version": "Versión",
|
||||
"versioned": "Con versiones",
|
||||
"versions_explain": "Crear varias versiones del mismo contenido: los usuarios pueden seleccionar qué versión ver",
|
||||
"change_control": "Control de cambios",
|
||||
"change_control_explain": "Seleccionar método de control de cambios",
|
||||
"pin": "Fijar",
|
||||
"pinned": "Fijado",
|
||||
"unpin": "Desfijar",
|
||||
"unpinned": "Desfijar",
|
||||
"blocks": "Bloques de contenido",
|
||||
"blocks_explain": "Los bloques de contenido proporcionan contenido reutilizable que se puede insertar en cualquier documento",
|
||||
"block_delete_confirm": "¿Está seguro de que desea eliminar este bloque de contenido reutilizable?",
|
||||
"actions": "Acciones",
|
||||
"activity": "Actividad",
|
||||
"activity_explain": "Informes de actividad del usuario que incluyen adiciones, vistas, actualizaciones y aprobaciones",
|
||||
"reports": "Informes",
|
||||
"content": "Contenido",
|
||||
"template": "Plantilla",
|
||||
"templates": "Plantillas",
|
||||
"document": "Documento",
|
||||
"documents": "Documentos",
|
||||
"attachments": "Archivos adjuntos",
|
||||
"history": "Historial",
|
||||
"bookmark": "Marcador",
|
||||
"bookmarks": "Marcadores",
|
||||
"bookmark_remove": "Eliminar marcador",
|
||||
"new": "Nuevo",
|
||||
"copy_link": "Copiar enlace",
|
||||
"created": "Creado",
|
||||
"markdown": "Markdown aceptado",
|
||||
"rename": "Cambiar nombre",
|
||||
"status": "Estado",
|
||||
"expiry": "Caducidad",
|
||||
"feedback": "Comentarios",
|
||||
"un_categorized": "Sin categorizar",
|
||||
|
||||
"toc": "Tabla de contenidos",
|
||||
"new_canvas": "Lienzo en blanco",
|
||||
"new_template": "Desde la plantilla",
|
||||
"new_import": "Importar archivos",
|
||||
"new_import_explain1": "Haga clic para seleccionar archivos o arrastre y suelte archivos",
|
||||
"new_import_explain2": ".doc, .docx, .md, .markdown",
|
||||
"new_content": "Nuevo contenido",
|
||||
"export_html": "Exportar como HTML",
|
||||
"export_html_explain1": "Exportar todo el contenido del espacio como HTML o seleccionar categorías",
|
||||
"export_html_explain2": "Todo el contenido del espacio se exportará como un único archivo HTML autocontenido",
|
||||
"import_convert": "Convirtiendo {1}",
|
||||
"import_success": "Convertido correctamente {1}",
|
||||
"add_recent": "Agregado recientemente",
|
||||
"update_recent": "Actualizado recientemente",
|
||||
"space_change": "Mover a otro espacio",
|
||||
"space_change_prompt": "Seleccionar espacio",
|
||||
"space_new": "Nuevo espacio",
|
||||
"space_name": "Nombre del espacio",
|
||||
"space_name_rules": "Solo caracteres y números",
|
||||
"space_description": "Descripción del espacio",
|
||||
"space_clone": "Clonar espacio",
|
||||
"space_select": "Seleccionar espacio",
|
||||
"space_delete": "Eliminar espacio",
|
||||
"space_delete_prompt": "Escriba el nombre del espacio para confirmar",
|
||||
"space_delete_warn": "¡Esto eliminará todos los documentos y plantillas dentro de este espacio!",
|
||||
"space_copy": "Copiar plantillas, permisos, documentos de un espacio existente",
|
||||
"space_copy_template": "Copiar plantillas",
|
||||
"space_copy_permission": "Copiar permisos",
|
||||
"space_copy_document": "Copiar documentos",
|
||||
"space_empty_state": "Agregar documentos mediante + CONTENT",
|
||||
"space_lockout": "Los permisos del espacio le impiden ver y crear documentos",
|
||||
"space_invite_message": "Hola, estoy compartiendo contigo el espacio {1} (en {2}) para que ambos podamos colaborar en la documentación.",
|
||||
"protection_none": "Se permiten cambios sin aprobación",
|
||||
"protection_lock": "Bloqueado, no se permiten cambios",
|
||||
"protection_review": "Los cambios requieren aprobación antes de su publicación",
|
||||
"template_published": "Plantilla publicada",
|
||||
"block_explain": "Los bloques de contenido proporcionan contenido reutilizable que se puede insertar en cualquier documento",
|
||||
"block_published": "Bloque publicado",
|
||||
"upload_attachment": "Subir archivos adjuntos",
|
||||
"content_revisions": "Revisiones de contenido",
|
||||
"content_revisions_explain": "Revisar cambios de contenido anteriores y revertir ediciones",
|
||||
"move_documents": "Mover documentos",
|
||||
"delete_documents": "Eliminar documentos",
|
||||
"feedback_enable": "Habilitar comentarios",
|
||||
"feedback_prompt": "Mensaje para comentarios",
|
||||
"feedback_prompt_hint": "Ingrese un mensaje solicitando comentarios del usuario",
|
||||
"feedback_prompt_explain": "Especifique el mensaje, p. ej. ¿Le resultó útil? ¿Encontraste lo que necesitabas?",
|
||||
"feedback_thanks": "¡Gracias por tus comentarios!",
|
||||
"feedback_help_yes": "¡Sí, gracias!",
|
||||
"feedback_help_no": "No realmente",
|
||||
"likes_prompt": "¿Esto te ayudó?",
|
||||
"delete_confirm": "¿Estás seguro de que deseas eliminar?",
|
||||
"category_assignment_summary": "Asignado a {1} documentos y visible para {2} usuarios/grupos",
|
||||
"category_no_access": "No tienes permiso de visualización para esta categoría",
|
||||
"category_default": "Categoría predeterminada para contenido nuevo",
|
||||
"category_default_explain": "Se aplica automáticamente a los documentos recién creados",
|
||||
"category_delete_confirm": "¿Estás seguro de que deseas eliminar esta categoría?",
|
||||
"category_permissions": "Permisos de categoría",
|
||||
"category_permissions_explain": "Seleccione quién puede ver los documentos dentro de la categoría",
|
||||
"category_none": "Este espacio no tiene categorías todavía",
|
||||
|
||||
"approval_anybody": "Se requiere la aprobación de cualquier aprobador",
|
||||
"approval_majority": "Se requiere la aprobación de la mayoría de los aprobadores",
|
||||
"approval_unanimous": "Se requiere la aprobación unánime de todos los aprobadores",
|
||||
"approval_pending": "Cambios pendientes",
|
||||
"approval_awaiting": "En espera de aprobación",
|
||||
"protection_type_open": "Abierto",
|
||||
"protection_type_protected": "Protegido",
|
||||
"protection_type_locked": "Bloqueado",
|
||||
"doc_request_contribution": "Solicitar contribución",
|
||||
"doc_request_feedback": "Solicitar comentarios",
|
||||
"doc_request_read": "Solicitar lectura",
|
||||
"doc_request_publication": "Solicitar publicación",
|
||||
"doc_request_approval": "Solicitar aprobación",
|
||||
"doc_withdraw_approval": "Solicitud de retiro",
|
||||
"doc_withdraw_approval_reason": "Explicación",
|
||||
"doc_withdraw_approval_reason_explain": "Nota útil que explica el motivo, p. ej. correcciones, adiciones",
|
||||
"doc_review_publish": "Puede revisar y aprobar los cambios",
|
||||
"doc_review_discard": "Me gustaría retirar esta solicitud de aprobación",
|
||||
"doc_contribution_pending": "Tiene un cambio pendiente",
|
||||
"doc_contribution_under_review": "Su solicitud de aprobación está bajo revisión",
|
||||
"doc_contribution_rejected": "Su cambio ha sido rechazado",
|
||||
"doc_contribution_review": "Revisar cambios ({1})",
|
||||
"doc_change_status": "{1} cambio(s) en progreso, {2} en espera de revisión, {3} rechazados",
|
||||
"doc_approve_reject": "Aprobar/Rechazar cambios",
|
||||
"doc_approve_method": "Método de aprobación",
|
||||
"doc_approve_status": "Estado de aprobación",
|
||||
"doc_approver_status": "{1} aprobaciones y {2} rechazos con {3} aprobadores involucrados en esta revisión",
|
||||
"doc_publish": "¿Puedes mover este documento de Borrador a En Vivo? ¡Estamos listos para publicarlo!",
|
||||
"doc_category_explain": "Asigna una o más categorías para ayudar a organizar el contenido dentro de este espacio",
|
||||
"doc_action_request_ask": "Preguntar",
|
||||
"doc_action_request_to": "Para",
|
||||
"doc_action_request_by": "Por",
|
||||
"revision_none": "No se han realizado revisiones",
|
||||
"revision_restore": "Restaurar sección",
|
||||
"revision_restore_confirm": "¿Estás seguro de que quieres restaurar esta revisión?",
|
||||
"template_save": "Guardar como plantilla",
|
||||
"template_name_explain": "Un buen nombre de plantilla transmite el tipo de documento",
|
||||
"template_desc_explain": "Explica el caso de uso para esta plantilla",
|
||||
"print_explain": "Imprime todo el contenido o selecciona secciones",
|
||||
"doc_delete_confirm": "¿Estás seguro de que quieres eliminar este documento?",
|
||||
"attachment_delete": "Eliminar archivo adjunto",
|
||||
"attachment_delete_confirm": "¿Está seguro de que desea eliminar este adjunto?",
|
||||
"link_insert": "Insertar vínculo",
|
||||
"link_type_section": "Sección",
|
||||
"link_type_section_explain": "Enlace al contenido de este documento",
|
||||
"link_type_attachment": "Archivo adjunto",
|
||||
"link_type_attachment_explain": "Enlace a un adjunto de este documento",
|
||||
"link_type_search": "Buscar",
|
||||
"link_type_search_explain": "Nombre del documento, contenido, nombre del adjunto",
|
||||
"link_type_network": "Red",
|
||||
"link_type_network_explain": "Especifique la ubicación de la unidad de red/recurso compartido/carpeta",
|
||||
"link_type_network_example": "p. ej. //recurso compartido/carpeta",
|
||||
"discard_changes": "Descartar cambios",
|
||||
"discard_confirm": "Ha realizado cambios: ¿desea continuar editando o descartar los cambios?",
|
||||
"share_expire_2": "en 2 días",
|
||||
"share_expire_7": "en 7 días",
|
||||
"share_expire_14": "en 14 días",
|
||||
"share_expire_30": "en 30 días",
|
||||
"share_expire_60": "en 60 días",
|
||||
"share_expire_90": "en 90 días",
|
||||
|
||||
"actions_mine": "Acciones asignadas a usted",
|
||||
"actions_none": "No tiene acciones",
|
||||
"actions_due": "vencidas",
|
||||
"actions_see_note": "leer nota",
|
||||
"actions_mark_complete": "marcar como completada",
|
||||
"actions_completed": "completada",
|
||||
"actions_see_more": "{1} acciones completadas →",
|
||||
"actions_requested": "Acciones que ha asignado a otros",
|
||||
"actions_requested_none": "No ha realizado ninguna solicitud",
|
||||
"actions_requested_more": "{1} solicitudes completadas recientemente →",
|
||||
"actions_requested_complete": "{1} solicitudes completadas →",
|
||||
"activity_period": "Período de tiempo",
|
||||
"activity_filter_past": "Pasado",
|
||||
"activity_filter_days": "Días",
|
||||
"activity_filter_for": "Durante",
|
||||
"audit_24": "24 horas",
|
||||
"audit_7": "7 días",
|
||||
"audit_14": "14 días",
|
||||
"audit_30": "30 días",
|
||||
"audit_90": "90 días",
|
||||
"chat_leave_comment": "Dejar comentario",
|
||||
"chat_applies_to": "Se aplica a",
|
||||
"chat_delete_confirm": "¿Está seguro de que desea eliminar este comentario?",
|
||||
"chat_reply_delete_confirm": "¿Está seguro de que desea eliminar esta respuesta?",
|
||||
"doc_secure_share": "Compartir mediante un enlace externo seguro",
|
||||
"doc_secure_shared_by": "Compartido por",
|
||||
"doc_version_viewed": "Cambiar el nombre de la versión",
|
||||
"doc_version_remove": "Desversionar",
|
||||
"doc_version_create": "Crear versión del documento",
|
||||
"doc_version_explain": "Las versiones se asignan a los documentos donde cada versión es un documento diferente.",
|
||||
"doc_version_label": "Etiqueta de versión",
|
||||
"doc_version_label_explain": "p. ej. 1.0, v1.0, Versión 1, Versión 2018.1",
|
||||
"doc_version_this": "Crear nueva versión de este documento",
|
||||
"doc_version_select": "o seleccionar otro documento",
|
||||
"doc_version_assign": "Asignar versión a este documento",
|
||||
"doc_version_dropdown": "<asignar versión a otro documento>",
|
||||
"doc_version_remove_confirm": "¿Está seguro de que desea eliminar esta versión y todo su contenido?",
|
||||
"doc_version_remove_name": "Confirme escribiendo el nombre del documento a continuación",
|
||||
"doc_version_unversion": "La operación de anulación de la versión hará que el documento sea independiente y mantendrá intacto todo el contenido.",
|
||||
"doc_version_unversion_confirm": "¿Está seguro de que desea anular la versión del documento?",
|
||||
"archived_content": "Contenido archivado",
|
||||
"archived_content_explain": "Marcar contenido archivado como activo",
|
||||
"unarchive_content": "Desarchivar contenido",
|
||||
|
||||
"document_permissions": "Permisos de documentos",
|
||||
"space_permissions": "Permisos de espacio",
|
||||
"space_permissions_explain": "Asignar permisos a usuarios o grupos e invitar a nuevos usuarios a este espacio",
|
||||
"space_permission_view": "Ver",
|
||||
"space_permission_view_explain": "Ver contenido dentro de este espacio",
|
||||
"space_permission_manage": "Administrar",
|
||||
"space_permission_manage_explain": "Administrar todos los aspectos del espacio excepto la eliminación",
|
||||
"space_permission_owner": "Propietario",
|
||||
"space_permission_owner_explain": "Administrar y eliminar espacio",
|
||||
"space_permission_doc_create": "Crear",
|
||||
"space_permission_doc_create_explain": "Puede crear nuevos documentos en el espacio",
|
||||
"space_permission_doc_edit": "Editar",
|
||||
"space_permission_doc_edit_explain": "Puede cambiar el contenido del documento",
|
||||
"space_permission_doc_delete": "Eliminar",
|
||||
"space_permission_doc_delete_explain": "Puede eliminar documentos del espacio",
|
||||
"space_permission_doc_move": "Mover",
|
||||
"space_permission_doc_move_explain": "Puede mover documentos de este espacio a otro espacio",
|
||||
"space_permission_doc_copy": "Copiar",
|
||||
"space_permission_doc_copy_explain": "Puede duplicar documentos",
|
||||
"space_permission_doc_template": "Plantillas",
|
||||
"space_permission_doc_template_explain": "Puede crear y publicar plantillas de documentos",
|
||||
"space_permission_doc_approval": "Aprobación",
|
||||
"space_permission_doc_approval_explain": "Puede (1) aprobar o rechazar cambios en los documentos; (2) mover documentos de borrador a activo",
|
||||
"space_permission_doc_draft": "Borrador",
|
||||
"space_permission_doc_draft_explain": "Puede ver y trabajar en documentos marcados como borrador",
|
||||
"space_permission_doc_version": "Versiones",
|
||||
"space_permission_doc_version_explain": "Puede crear versiones de documentos y vincularlas",
|
||||
"space_permission_add_user": "Agregar usuarios a este espacio",
|
||||
"space_permission_invite_user": "Invitar usuarios a este espacio",
|
||||
"space_permission_invite_explain": "Separar con comas varias direcciones de correo electrónico",
|
||||
|
||||
"section_insert": "Insertar sección",
|
||||
"section_insert_here": "Insertar sección aquí",
|
||||
"section_copy_explain": "Esta sección y todas las secciones anidadas se copiarán al documento seleccionado",
|
||||
"section_move_explain": "Esta sección y todas las secciones anidadas se moverán al documento seleccionado",
|
||||
"section_delete": "¿Está seguro de que desea eliminar esta sección?",
|
||||
"section_delete_children": "Eliminar también las secciones secundarias",
|
||||
"section_publish": "Publicar bloque de contenido reutilizable",
|
||||
"section_publish_name_explain": "Proporcionar un título breve para el bloque de contenido reutilizable",
|
||||
"section_publish_desc_explain": "Descripción breve para ayudar a otros a comprender el bloque de contenido reutilizable",
|
||||
"section_airtable": "Airtable",
|
||||
"section_airtable_explain": "Parte hoja de cálculo, parte base de datos y totalmente flexible (https://airtable.com)",
|
||||
"section_airtable_code": "Insertar Airtable código",
|
||||
"section_code_tip": "Nombre conciso que describe el fragmento de código",
|
||||
"section_drawio": "Diagrams.net",
|
||||
"section_drawio_explain": "Para crear diagramas de flujo, diagramas de procesos, organigramas, UML, diagramas ER, diagramas de red y mucho más (https://www.diagrams.net)",
|
||||
"section_iframe": "iFrame",
|
||||
"section_iframe_explain": "Incrustar un iFrame",
|
||||
"section_iframe_code": "Código de incrustación de iFrame",
|
||||
"section_gemini": "Gemini",
|
||||
"section_gemini_explain": "Software de soporte técnico y seguimiento de problemas empresariales Gemini (https://www.countersoft.com)",
|
||||
"section_gemini_url": "URL de Gemini",
|
||||
"section_gemini_url_explain": "p. ej. Español: https://helpdesk.countersoft.com",
|
||||
"section_gemini_key": "Clave API (del perfil de usuario)",
|
||||
"section_gemini_workspace": "Espacio de trabajo",
|
||||
"section_jira": "Software Jira",
|
||||
"section_jira_explain": "Jira proporciona seguimiento de problemas y software ágil",
|
||||
"section_jira_admin": "El administrador de su comunidad Documize debe proporcionar detalles de conexión de Jira antes del uso.",
|
||||
"section_jira_no_auth": "Conector Jira no autenticado",
|
||||
"section_papertrail": "Papertrail",
|
||||
"section_papertrail_explain": "Muestra tus registros basados en la nube (https://papertrailapp.com)",
|
||||
"section_papertrail_key": "Clave API de Papertrail",
|
||||
"section_papertrail_search": "Consulta de búsqueda",
|
||||
"section_papertrail_search_explain": "Determina qué entradas de registro quieres mostrar, p. ej. bob OR (algunafrase AND sally)",
|
||||
"section_papertrail_max": "Resultados máximos",
|
||||
"section_papertrail_max_explain": "¿Cuántas entradas de registro desea?",
|
||||
"section_papertrail_group": "Grupo",
|
||||
"section_papertrail_group_explain": "Grupo de Papertrail opcional",
|
||||
"section_pdf": "Visualizador de PDF",
|
||||
"section_pdf_upload_explain": "Se utilizará el primer PDF cargado",
|
||||
"section_pdf_height": "Altura de la vista previa",
|
||||
"section_pdf_height_explain": "¿Qué altura tiene la vista previa del PDF?",
|
||||
"section_pdf_start": "Página de inicio",
|
||||
"section_pdf_start_explain": "La primera página que se mostrará",
|
||||
"section_pdf_sidebar": "Barra lateral",
|
||||
"section_pdf_sidebar_explain": "Opcionalmente, establezca el contenido de la barra lateral",
|
||||
"section_pdf_sidebar_none": "Ninguno",
|
||||
"section_pdf_sidebar_bookmark": "Marcadores",
|
||||
"section_pdf_sidebar_thumbnail": "Miniaturas",
|
||||
"section_plantuml": "PlantUML",
|
||||
"section_plantuml_explain": "Crear diagramas UML a partir de un lenguaje de texto simple (http://plantuml.com)",
|
||||
"section_plantuml_link": "Diagrama PlantUML",
|
||||
"section_plantuml_type_sequence": "Secuencia",
|
||||
"section_plantuml_type_usecase": "Caso de uso",
|
||||
"section_plantuml_type_class": "Clase",
|
||||
"section_plantuml_type_activity": "Actividad",
|
||||
"section_plantuml_type_activity2": "Actividad (nueva sintaxis)",
|
||||
"section_plantuml_type_component": "Componente",
|
||||
"section_plantuml_type_state": "Estado",
|
||||
"section_tabular_import_csv": "Importar CSV",
|
||||
"section_tabular_csv": "CSV a tabla",
|
||||
"section_tabular_warn": "Nota: los datos de la tabla existente se reemplazarán",
|
||||
"section_tabular_paste": "Pegar datos CSV",
|
||||
"section_tabular_format": "Se admiten los delimitadores comunes",
|
||||
"section_tabular_first_row": "Encabezado de la primera fila",
|
||||
"section_tabular_first_row_explain": "Habilitar si la primera fila contiene encabezados",
|
||||
"section_trello": "Trello",
|
||||
"section_trello_explain": "Trello es la forma visual de administrar sus proyectos y organizar cualquier cosa (https://trello.com)",
|
||||
"section_trello_none": "No tiene tableros de equipo para compartir; los tableros personales nunca se muestran",
|
||||
"section_trello_admin": "Su administrador de la Comunidad Documize debe configurar Trello antes de usarlo",
|
||||
"section_trello_board": "Tablero",
|
||||
"section_trello_list": "Lista",
|
||||
|
||||
"login_cas": "Authenticating with CAS...",
|
||||
"login_cass_error": "CAS authentication failure",
|
||||
"login_keycloak": "Authenticating with Keycloak...",
|
||||
"login_keycloak_error": "Keycloak authentication failure",
|
||||
"login_invalid": "Invalid credentials",
|
||||
"forgot_password": "Forgot your password?",
|
||||
"reset_password": "Reset Password",
|
||||
"reset_password_next": "Thanks. Check your email for instructions.",
|
||||
"password_strong": "Choose a strong password",
|
||||
"password_match": "Passwords must match",
|
||||
"welcome": "Welcome to Documize",
|
||||
"welcome_explain": "Let's set up your account and get you started",
|
||||
"profile_explain": "Manage your profile and password",
|
||||
"search_hint": "keywords, tags",
|
||||
"search_too_short": "Your search query is too short",
|
||||
"search_doc_name": "Document name",
|
||||
"search_doc_content": "Document content",
|
||||
"search_tag_name": "Tag name",
|
||||
"search_attachment_name": "Attachment name",
|
||||
"search_example_title": "Query examples",
|
||||
"search_explain": "Find content using keywords and operators",
|
||||
"search_example1": "Show results that contain at least one of the two words",
|
||||
"search_example2": "Show results that contain both words",
|
||||
"search_example3": "Show results that contain the word \"apple\", but rank rows higher if they also contain \"macintosh\"",
|
||||
"search_example4": "Show results that contain the word \"apple\" but not \"macintosh\"",
|
||||
"search_example5": "Show results that contain the words \"apple\" and \"turnover\", or \"apple\" and \"strudel\" (in any order), but rank \"apple turnover\" higher than \"apple strudel\"",
|
||||
"search_example6": "Show results that contain words such as \"apple\", \"apples\", \"applesauce\", or \"applet\"",
|
||||
"search_example7": "Show results that contain the exact phrase \"some words\" (for example, rows that contain \"some words of wisdom\" but not \"some noise words\")",
|
||||
"search_example8": "Show results that contain either word",
|
||||
"search_example9": "Show results that have \"google\", either \"apple\" or \"microsoft\" but not \"ibm\"",
|
||||
"search_example10": "Show results that contain words that start with \"apple\", such as \"applesauce\" or \"applet\"",
|
||||
"space_density_complete": "Complete",
|
||||
"space_density_comfort": "Comfort",
|
||||
"space_density_compact": "Compact",
|
||||
|
||||
"backup_explain1": "Documize Community es una aplicación multiusuario que permite que tanto 'tech.mycompany.com' como 'sales.mycompany.com' se ejecuten utilizando el mismo ejecutable/base de datos. Como administrador global de Documize Community, realizará una copia de seguridad completa de todo el sistema en todos los inquilinos. El administrador de inquilinos de Documize Community puede iniciar sesión para realizar una copia de seguridad a nivel de inquilino (por ejemplo, marketing.mycompany.com).",
|
||||
"backup_explain2": "Documize Community es una aplicación multiusuario que permite que tanto 'tech.mycompany.com' como 'sales.mycompany.com' se ejecuten utilizando el mismo ejecutable/base de datos. Como administrador global de Documize Community, realizará una copia de seguridad completa de todo el sistema en todos los inquilinos. Como administrador de inquilinos de Documize Community, puede realizar una copia de seguridad a nivel de inquilino (por ejemplo, marketing.mycompany.com).",
|
||||
"backup_explain3": "Puede llevar varios minutos completar el proceso de copia de seguridad; tenga paciencia mientras se realiza la operación de copia de seguridad en progreso.",
|
||||
"backup_retain": "Mantener archivo de respaldo en el servidor",
|
||||
"backup_running": "Respaldo en ejecución, espere...",
|
||||
"backup_tenant": "Inquilino de respaldo",
|
||||
"backup_system": "Sistema de respaldo",
|
||||
"backup_failed": "Respaldo fallido -- verifique los registros del servidor",
|
||||
"backup_success": "Respaldo exitoso",
|
||||
"backup_start": "Iniciar respaldo",
|
||||
"backup_run": "Ejecutar respaldo",
|
||||
"restore_explain1": "La restauración desde un respaldo del sistema solo debe realizarse en una base de datos de Documize Community vacía.",
|
||||
"restore_explain2": "La operación de restauración recreará usuarios, grupos, permisos, espacios, categorías y contenido.",
|
||||
"restore_explain3": "Puede tomar varios minutos completar el proceso de restauración -- tenga paciencia mientras la operación de restauración está en progreso.",
|
||||
"restore_select_file": "Elija archivo de respaldo",
|
||||
"restore_running": "Espere, Restaurar en ejecución...",
|
||||
"restore_failed": "Falló la restauración -- verifique los registros del servidor",
|
||||
"restore_success": "Restauración completada -- reinicie su navegador e inicie sesión",
|
||||
"restore_confirm": "Confirmar restauración",
|
||||
"restore_confirm_input": "Escriba RESTORE para comenzar el proceso",
|
||||
"restore_warn": "Solo debe restaurar en una instancia de Documize Community vacía",
|
||||
"changelog_available": "Actualización del producto disponible",
|
||||
"changelog_guidance": "Para actualizar, reemplace el binario existente y reinicie Documize Community.",
|
||||
"customize_name": "Nombre del sitio",
|
||||
"customize_name_explain": "Proporcione un título corto para esta instancia de Documize Community",
|
||||
"customize_message": "Mensaje del sitio",
|
||||
"customize_message_explain": "Proporcione un mensaje corto que explique esta instancia de Documize Community",
|
||||
"customize_theme": "Tema del sitio",
|
||||
"customize_logo": "Logotipo del sitio",
|
||||
"customize_logo_default": "Usar predeterminado",
|
||||
"customize_logo_upload": "Cargar personalizado",
|
||||
"customize_logo_explain": "Puede elegir cargar un logotipo pequeño (p. ej. 64px x 64px)",
|
||||
"customize_subdomain": "Subdominio de la URL del sitio",
|
||||
"customize_subdomain_explain": "Si está alojando en 'docs.example.org', entonces el valor del subdominio debe establecerse en 'docs'",
|
||||
"customize_anon": "Espacios públicos visibles para usuarios anónimos",
|
||||
"customize_anon_explain": "Compartir contenido con visitantes del sitio no autenticados",
|
||||
"customize_conversion_url": "URL del servicio de conversión",
|
||||
"customize_conversion_explain": "Punto final para gestionar la importación/exportación",
|
||||
"customize_tags": "Etiquetas máximas por documento",
|
||||
"customize_tags_explain": "Cuántas etiquetas se pueden asignar a un documento (entre 3 y 10 etiquetas)",
|
||||
"integration_jira_url": "URL",
|
||||
"integration_jira_url_explain": "Nombre de dominio completo para su Jira ejemplo, http://jira.example.org",
|
||||
"integration_jira_username": "Nombre de usuario",
|
||||
"integration_jira_username_explain": "Su nombre de usuario/correo electrónico de inicio de sesión de Jira",
|
||||
"integration_jira_password": "Contraseña",
|
||||
"integration_jira_password_explain": "Proporcione un token de API si usa Atlassian Cloud o una contraseña al alojar Jira por su cuenta",
|
||||
"integration_trello_appkey": "Clave de la aplicación",
|
||||
"search_reindex": "Puede tomar hasta 30 minutos reconstruir el índice de búsqueda",
|
||||
"search_reindex_rebuild": "Reconstruir",
|
||||
"search_reindex_start": "Iniciando el proceso de reindexación de búsqueda",
|
||||
"search_reindex_finish": "Reindexación de búsqueda completada",
|
||||
"smtp_host": "Host",
|
||||
"smtp_host_explain": "p. ej. my.host.com",
|
||||
"smtp_port": "Puerto",
|
||||
"smtp_port_explain": "p. ej. 587",
|
||||
"smtp_username": "Nombre de usuario",
|
||||
"smtp_username_explain": "p. ej. Nombre de usuario de inicio de sesión para el servidor SMTP",
|
||||
"smtp_password": "Contraseña",
|
||||
"smtp_password_explain": "p. ej. Contraseña de inicio de sesión para el servidor SMTP",
|
||||
"smtp_sender_email": "Correo electrónico del remitente",
|
||||
"smtp_sender_email_explain": "p. ej. usuario@example.org",
|
||||
"smtp_sender_name": "Nombre del remitente",
|
||||
"smtp_sender_name_explain": "p. ej. Documize",
|
||||
"smtp_fqdn": "Nombre de dominio completo del servidor remitente",
|
||||
"smtp_fqdn_explain": "(opcional) SMTP puede requerir un nombre de dominio válido, p. ej. docs.example.org",
|
||||
"smtp_anon_auth": "Autenticación anónima (ignorar credenciales)",
|
||||
"smtp_base64": "Credenciales de codificación Base64",
|
||||
"smtp_ssl": "Usar SSL",
|
||||
"smtp_save_test": "Guardar y probar",
|
||||
"smtp_sent_test_email": "Enviándole un correo electrónico de prueba",
|
||||
"smtp_missing": "Faltan configuraciones del servidor de correo",
|
||||
"space_admin_export": "Exportar todo el contenido",
|
||||
"space_admin_export_running": "Exportación en ejecución...",
|
||||
"space_admin_make_owner": "Agregarme como propietario",
|
||||
"space_admin_empty": "No hay espacios compartidos para administrar",
|
||||
"space_admin_delete_title": "Eliminación de espacio",
|
||||
"space_admin_delete_check": "¿Está seguro de que desea eliminar este espacio y todos los documentos?",
|
||||
"space_admin_confirm": "Escriba el nombre del espacio para confirmar",
|
||||
"space_admin_confirm_explain": "¡Esto eliminará todos los documentos y plantillas dentro de este espacio!",
|
||||
"label_add": "Agregar etiqueta",
|
||||
"label_update": "Actualizar etiqueta",
|
||||
"label_delete": "Eliminar etiqueta",
|
||||
"label_delete_confirm": "¿Está seguro de que desea eliminar la etiqueta {1}?",
|
||||
"user_admin_add": "Agregar usuarios",
|
||||
"user_admin_bulk": "Carga masiva",
|
||||
"user_admin_bulk_format": "Lista delimitada por comas: nombre, apellido, correo electrónico",
|
||||
"group_add": "Agregar Grupo",
|
||||
"group_name_explain": "Ingrese el nombre del grupo, p. ej. Administradores, desarrolladores, equipo Acme",
|
||||
"group_member_add": "Agregar miembro",
|
||||
"group_member_remove": "Eliminar miembro",
|
||||
"group_delete": "Eliminar grupo",
|
||||
"group_delete_confirm": "¿Está seguro de que desea eliminar este grupo?",
|
||||
"group_delete_name": "Escriba el nombre del grupo para confirmar",
|
||||
"group_delete_name_explain": "Esto eliminará la información de membresía del grupo y los permisos asociados",
|
||||
"group_none": "No hay grupos",
|
||||
"group_edit": "Editar grupo",
|
||||
"find_user": "Buscar usuarios",
|
||||
"find_user_syntax": "Buscar nombre, apellido, correo electrónico",
|
||||
"user_max_display": "Máximo de usuarios para mostrar",
|
||||
"user_assign_group": "Asignar grupos de usuarios",
|
||||
"user_delete_confirm": "¿Está seguro de que desea eliminar al usuario {1}?",
|
||||
"user_selected_delete_confirm": "¿Está seguro de que desea eliminar los usuarios seleccionados?",
|
||||
"user_delete": "Eliminar usuario",
|
||||
"permission_spaces": "Espacios",
|
||||
"permission_spaces_explain": "Puede agregar espacios, tanto personales como compartidos con otros",
|
||||
"permission_visible": "Visible",
|
||||
"permission_visible_explain": "Puede ver los nombres de los usuarios y grupos, puede deshabilitarlos para usuarios externos como clientes/socios",
|
||||
"permission_admin": "Administrador",
|
||||
"permission_admin_explain": "Puede administrar todos los aspectos de Documize Community, como esta pantalla",
|
||||
"permission_analytics": "Análisis",
|
||||
"permission_analytics_explain": "Puede ver informes analíticos",
|
||||
"permission_active": "Activo",
|
||||
"permission_active_explain": "Puede iniciar sesión y usar Documize Community",
|
||||
"auth_role_space": "Puede crear espacios",
|
||||
"auth_disable_logout": "Deshabilitar cierre de sesión",
|
||||
"auth_dual_login": "Inicio de sesión dual",
|
||||
"auth_dual_login_explain": "Habilitar inicio de sesión a través de LDAP y correo electrónico/contraseña normal (útil para probar LDAP)",
|
||||
"auth_email_password": "Correo electrónico/contraseña integrados",
|
||||
"auth_connect_keycloak": "Conectarse al servidor de autenticación",
|
||||
"auth_connect_ldap": "Conectarse a LDAP/Active Directory",
|
||||
"auth_connect_cas": "Conectarse al servidor de autenticación central",
|
||||
"auth_keycloak_running": "Sincronización de usuarios de Keycloak en ejecución...",
|
||||
"auth_keycloak_sync": "Sincronizar con Keycloak",
|
||||
"auth_ldap_running": "Sincronización de usuarios de LDAP en ejecución...",
|
||||
"auth_ldap_sync": "Sincronizar con LDAP",
|
||||
"auth_keycloak_url": "URL del servidor de Keycloak",
|
||||
"auth_keycloak_realm": "Dominio de Keycloak",
|
||||
"auth_keycloak_pk": "Clave pública de dominio Keycloak",
|
||||
"auth_keycloak_pk_explain": "Copiar la clave pública RSA desde Configuración de dominio > Claves",
|
||||
"auth_keycloak_oidc": "ID de cliente de Keycloak OIDC",
|
||||
"auth_keycloak_group": "ID de grupo de Keycloak (opcional)",
|
||||
"auth_keycloak_group_explain": "Si desea sincronizar usuarios en un grupo en particular (por ejemplo, 'Usuarios de la comunidad de Documize'), proporcione la ID de grupo (por ejemplo, 511d8b61-1ec8-45f6-bc8d-5de64d54c9d2)",
|
||||
"auth_keycloak_username": "Nombre de usuario de Keycloak",
|
||||
"auth_keycloak_username_explain": "Se utiliza para conectar con Keycloak y sincronizar usuarios con Documize Community (crear usuario en Master Realm y asignar el rol 'view-users' contra el Realm especificado anteriormente)",
|
||||
"auth_keycloak_password": "Contraseña de Keycloak",
|
||||
"auth_keycloak_password_explain": "Se utiliza para conectar con Keycloak y sincronizar usuarios con Documize Community",
|
||||
"auth_ldap_server": "Servidor LDAP",
|
||||
"auth_ldap_server_explain": "Dirección IP o de host, p. ej. ldap.example.org, 127.0.0.1",
|
||||
"auth_ldap_port": "Puerto del servidor LDAP",
|
||||
"auth_ldap_port_explain": "Número de puerto, p. ej. 389",
|
||||
"auth_ldap_base": "DN base",
|
||||
"auth_ldap_base_explain": "Punto de inicio para filtros de búsqueda, p. ej. ou=users,dc=example,dc=com",
|
||||
"auth_ldap_bind": "DN de enlace",
|
||||
"auth_ldap_bind_explain": "Credenciales de inicio de sesión para el servidor LDAP",
|
||||
"auth_ldap_password": "Contraseña de enlace",
|
||||
"auth_ldap_filter_user": "Filtro de usuario",
|
||||
"auth_ldap_filter_user_explain1": "Filtro de búsqueda para encontrar usuarios, p. ej. (|(objectClass=person)(objectClass=user)(objectClass=inetOrgPerson))",
|
||||
"auth_ldap_filter_user_explain2": "Especificar filtro de usuario y/o filtro de grupo",
|
||||
"auth_ldap_filter_group": "Filtro de grupo",
|
||||
"auth_ldap_filter_group_explain": "Filtro de búsqueda para encontrar usuarios a través de grupos, p. ej. (&(objectClass=group)(|(cn=ship_crew)(cn=admin_staff)))",
|
||||
"auth_ldap_rdn": "Atributo de usuario RDN",
|
||||
"auth_ldap_rdn_explain1": "Atributo de nombre de usuario/inicio de sesión, p. ej. uid en LDAP, sAMAccountName en Active Directory",
|
||||
"auth_ldap_rdn_explain2": "Atributos de usuario utilizados para recuperar datos al usar el filtro de usuario",
|
||||
"auth_ldap_firstname": "Nombre del atributo de usuario",
|
||||
"auth_ldap_firstname_explain": "Atributo de nombre, p. ej. givenName",
|
||||
"auth_ldap_lastname": "Atributo de usuario Apellido",
|
||||
"auth_ldap_lastname_explain": "Atributo de apellido, p. ej. sn",
|
||||
"auth_ldap_email": "Correo electrónico del atributo de usuario",
|
||||
"auth_ldap_email_explain": "Atributo de correo electrónico, p. ej. mail",
|
||||
"auth_ldap_group": "Miembro del atributo de grupo",
|
||||
"auth_ldap_group_explain1": "Atributo que identifica a un miembro individual del grupo, p. ej. miembro o miembro único",
|
||||
"auth_ldap_group_explain2": "Atributos de grupo utilizados para recuperar datos al usar el filtro de grupo",
|
||||
"auth_ldap_preview": "Vista previa de LDAP",
|
||||
"auth_ldap_preview_result": "Conexión exitosa, se encontraron {1} usuarios",
|
||||
"auth_ldap_preview_error": "No se puede conectar",
|
||||
"auth_cas_url": "URL del servidor CAS",
|
||||
"auth_cas_url_explain": "p. ej. http://localhost:8888/auth",
|
||||
"auth_cas_back_url": "URL CAS de Documize",
|
||||
"auth_cas_back_url_explain": "p. ej. http://Documize-URL/auth/cas",
|
||||
"administration": "Administración",
|
||||
"admin_general": "General",
|
||||
"admin_general_explain": "Opciones para personalizar Documize Community",
|
||||
"admin_user_management": "Administración de usuarios",
|
||||
"admin_user_management_explain": "Administrar información básica, contraseñas y permisos",
|
||||
"admin_user_groups": "Grupos de usuarios",
|
||||
"admin_user_groups_explain": "Definir grupos para una administración más sencilla de los usuarios y los permisos",
|
||||
"admin_integrations": "Integraciones",
|
||||
"admin_integrations_explain": "Habilitar y configurar integraciones de terceros",
|
||||
"admin_mail_server": "Servidor de correo",
|
||||
"admin_mail_server_explain": "Especificar los detalles del servidor de correo necesarios para enviar correos electrónicos de invitación y notificación a los usuarios",
|
||||
"admin_audit_log": "Registro de auditoría",
|
||||
"admin_backup": "Copia de seguridad y restauración",
|
||||
"admin_backup_explain": "Exportar todo el contenido a un único archivo zip autónomo",
|
||||
"admin_billing": "Facturación",
|
||||
"admin_changelog": "Registro de cambios",
|
||||
"admin_auth_explain": "Elegir proveedor de autenticación de usuarios: Documize, Redhat Keycloak, LDAP/AD, Central Authentication Server",
|
||||
"admin_spaces_explain": "Eliminar espacios, tomar posesión de espacios compartidos y huérfanos",
|
||||
"admin_labels_explain": "Agrupar y navegar por espacios con etiquetas visuales",
|
||||
"admin_search_explain": "Reconstruir el índice de búsqueda",
|
||||
"setup_default_message": "La instancia de la Comunidad Documize contiene toda nuestra documentación",
|
||||
"get_in_touch": "Póngase en contacto",
|
||||
"product_feedback": "¿Tiene una idea, sugerencia o algún comentario sobre un producto?",
|
||||
"product_news": "Novedades sobre el producto",
|
||||
"product_news_explain": "Últimas novedades y actualizaciones sobre el producto",
|
||||
"product_update": "Actualización disponible",
|
||||
"product_whats_new": "Novedades",
|
||||
"product_activation_key_missing": "Falta la clave de activación",
|
||||
"account_update": "Actualizar cuenta",
|
||||
"404": "¡Ups! No se pudo encontrar esa página.",
|
||||
"404_explain": "¿Quizás el contenido que está buscando ya no está disponible?",
|
||||
"close_account": "Cierre mi cuenta de Documize.",
|
||||
"third_party": "La comunidad de Documize utiliza bibliotecas y componentes de código abierto de terceros",
|
||||
|
||||
"server_ldap_error1": "Error: omitiendo la sincronización de usuarios con LDAP ya que no es la opción configurada",
|
||||
"server_ldap_error2": "Error: no se pueden leer los datos de configuración de LDAP",
|
||||
"server_ldap_error3": "Error: no se pueden obtener los usuarios de LDAP: {1}",
|
||||
"server_ldap_complete": "Sincronización completa con el servidor LDAP",
|
||||
"server_ldap_summary": "La sincronización LDAP encontró {1} usuarios, se agregaron {2} nuevos usuarios, se ignoraron {3} usuarios con datos faltantes",
|
||||
"server_keycloak_error1": "Error: omitiendo la sincronización de usuarios con LDAP Keycloak ya que no es la opción configurada",
|
||||
"server_keycloak_error2": "Error: no se pueden leer los datos de configuración de Keycloak",
|
||||
"server_keycloak_error3": "Error: no se pueden obtener los usuarios de Keycloak: {1}",
|
||||
"server_keycloak_summary": "La sincronización de Keycloak encontró {1} usuarios, se agregaron {2} nuevos usuarios, se ignoraron {3} usuarios con datos faltantes",
|
||||
"server_smtp_success": "Correo electrónico enviado correctamente",
|
||||
"server_smtp_test_subject": "Prueba SMTP de Documize Community",
|
||||
"server_smtp_test_body": "Este es un correo electrónico de prueba de Documize Community que utiliza la configuración SMTP actual",
|
||||
"server_error_user": "Error: no se pueden obtener los usuarios",
|
||||
"server_error_org": "Error: no se puede obtener el registro de la organización",
|
||||
|
||||
"mail_template_click_here": "Haga clic aquí",
|
||||
"mail_template_sender": "Su colega",
|
||||
"mail_template_approval": "{1} le ha otorgado el rol de aprobación de documentos",
|
||||
"mail_template_approval_explain": "Se le solicita que apruebe todos los cambios en el siguiente documento:",
|
||||
"mail_template_password": "Su contraseña temporal:",
|
||||
"mail_template_user_invite": "{1} le ha invitado a la Comunidad Documize",
|
||||
"mail_template_user_existing": "{1} le ha invitado a su cuenta de la Comunidad Documize",
|
||||
"mail_template_reset_password": "Su solicitud de restablecimiento de contraseña de la Comunidad Documize",
|
||||
"mail_template_shared": "{1} ha compartido el espacio {2} con usted",
|
||||
"mail_template_invited": "{1} ha compartido el espacio {2} con usted en la Comunidad Documize",
|
||||
"mail_template_approval_request": "{1} ha solicitado la aprobación de cambio de documento",
|
||||
"mail_template_approval_request_explain": "Apruebe el cambio al documento titulado {1}",
|
||||
"mail_template_approval_withdraw": "{1} ha retirado la solicitud de aprobación de cambio de documento",
|
||||
"mail_template_approval_withdraw_explain": "{1} La solicitud de aprobación ha sido retirada para el documento",
|
||||
"mail_template_publish_explain": "Puede publicar el documento {1} cambiando el estado de Borrador a En vivo.",
|
||||
"mail_template_reviewer": "Revisión de cambio de documento completada por {1}",
|
||||
"mail_template_approval_1": "Su cambio no ha sido publicado porque ningún revisor aprobó el cambio.",
|
||||
"mail_template_approval_2": "Su cambio no ha sido publicado porque la mayoría de los revisores no aprobaron el cambio.",
|
||||
"mail_template_approval_3": "Su cambio no ha sido publicado porque no se obtuvo la aprobación unánime logrado.",
|
||||
"mail_template_approval_4": "Su cambio ha sido publicado porque un revisor aprobó el cambio.",
|
||||
"mail_template_approval_5": "Su cambio ha sido publicado porque la mayoría de los revisores aprobaron el cambio.",
|
||||
"mail_template_approval_6": "Su cambio ha sido publicado con aprobación unánime.",
|
||||
"mail_template_approval_7": "Su cambio aún está bajo revisión y requiere que cualquier otro revisor apruebe el cambio.",
|
||||
"mail_template_approval_8": "Su cambio aún está bajo revisión y requiere que la mayoría de los revisores aprueben el cambio.",
|
||||
"mail_template_approval_9": "Su cambio aún está bajo revisión y necesita aprobación unánime.",
|
||||
"mail_template_review_outcome": "{1} revisó su cambio para el documento {2} y fue marcado como {3}. {4}",
|
||||
"mail_template_action_read": "Lea el documento {1} antes del {2}.",
|
||||
"mail_template_action_feedback": "Envíe comentarios sobre el documento {1} antes del {2}.",
|
||||
"mail_template_action_contribute": "Contribuya con contenido al documento {1} antes del {2}.",
|
||||
"mail_template_publish_request": "{1} ha solicitado la publicación del documento",
|
||||
"mail_template_action_assigned": "{1} le ha asignado una acción de documento",
|
||||
"mail_template_action_done": "{1} ha completado su acción de documento",
|
||||
"mail_template_action_read_done": "{1} ha leído el documento {2} (fecha de publicación: {3})",
|
||||
"mail_template_action_feedback_done": "{1} ha proporcionado comentarios sobre el documento {2} (fecha de publicación: {3})",
|
||||
"mail_template_action_contribute_done": "{1} ha contribuido con contenido a documento {2} (fecha de entrega: {3})",
|
||||
"mail_template_share_doc": "{1} ha compartido un documento contigo",
|
||||
"mail_template_share_viewed": "{1} ha sido visto",
|
||||
"mail_template_feedback_received": "{1} te ha enviado comentarios sobre {2}"
|
||||
}
|
758
gui/public/i18n/fr-FR.json
Normal file
758
gui/public/i18n/fr-FR.json
Normal file
|
@ -0,0 +1,758 @@
|
|||
{
|
||||
"all": "Tous",
|
||||
"none": "Aucun",
|
||||
"never": "Jamais",
|
||||
"add": "Ajouter",
|
||||
"added": "Ajouté",
|
||||
"activate": "Activer",
|
||||
"summary": "Résumé",
|
||||
"approve": "Approuvé",
|
||||
"authenticate": "Authentifier",
|
||||
"cancel": "Annuler",
|
||||
"close": "Fermer",
|
||||
"copy": "Copier",
|
||||
"copied": "Copié",
|
||||
"delete": "Supprimer",
|
||||
"deleted": "Supprimé",
|
||||
"remove": "Supprimer",
|
||||
"duplicate": "Dupliquer",
|
||||
"duplicated": "Dupliqué",
|
||||
"edit": "Éditer",
|
||||
"edited": "Édité",
|
||||
"download": "Télécharger",
|
||||
"upload": "Uploader",
|
||||
"uploaded": "Uploadé",
|
||||
"import": "Importer",
|
||||
"export": "Exporter",
|
||||
"exported": "Exporté",
|
||||
"pdf": "PDF",
|
||||
"test": "Test",
|
||||
"configure": "Configurer",
|
||||
"error": "Erreur",
|
||||
"file": "Fichiers",
|
||||
"insert": "Insérer",
|
||||
"invite": "Inviter",
|
||||
"message": "Message",
|
||||
"join": "Rejoindre",
|
||||
"leave": "Quitter",
|
||||
"login": "Se connecter",
|
||||
"logout": "Se déconnecter",
|
||||
"authentication": "Authentification",
|
||||
"move": "Déplacer",
|
||||
"moved": "Déplacé",
|
||||
"next": "Suivant",
|
||||
"ok": "OK",
|
||||
"preview": "Prévisualiser",
|
||||
"preview_wait": "Génération de la visualisation...",
|
||||
"pdf_prepare": "Préparation du PDF...",
|
||||
"publish": "Publier",
|
||||
"print": "Imprimer",
|
||||
"reject": "Rejeter",
|
||||
"rejected": "Rejeté",
|
||||
"reply": "Répondre",
|
||||
"replied": "Répondu",
|
||||
"reset": "Réinitialiser",
|
||||
"request": "Demander",
|
||||
"requested": "Demandé",
|
||||
"save": "Sauvegarde",
|
||||
"saved": "Sauvegardé",
|
||||
"search": "Recherche",
|
||||
"send": "Envoyé",
|
||||
"share": "Partagé",
|
||||
"discard": "Rejeter",
|
||||
"continue": "Continuer",
|
||||
"code": "code",
|
||||
"signin": "Se connecter",
|
||||
"sort": "Trier",
|
||||
"sort_ascending": "Ascendant",
|
||||
"sort_descending": "Descendant",
|
||||
"sort_by_name": "Nom",
|
||||
"sort_by_created": "Date de création",
|
||||
"sort_by_revised": "Dernière modification",
|
||||
"unassigned": "Non attribué",
|
||||
"update": "Mettre à jour",
|
||||
"updating": "Mis à jour",
|
||||
"viewed": "Vue",
|
||||
"name": "Nom",
|
||||
"description": "Description",
|
||||
"excerpt": "Extrait",
|
||||
"icon": "Icône",
|
||||
"color": "Couleur",
|
||||
"visibility": "Visibilité",
|
||||
"running": "En cours...",
|
||||
"firstname": "Prénom",
|
||||
"lastname": "Nom",
|
||||
"email": "Email",
|
||||
"email_recipient": "Destinataire Email",
|
||||
"password": "Mot de Passe",
|
||||
"password_new": "Nouveau Mot de Passe",
|
||||
"username": "Nom d'utilisateur",
|
||||
"user": "Utilisateur",
|
||||
"password_confirm": "Confimer Mot de Passe",
|
||||
"encryption": "Chiffrement",
|
||||
"notice": "Remarque",
|
||||
"backup": "Sauvegarder",
|
||||
"restore": "Restaurer",
|
||||
"completed": "Terminé",
|
||||
"please_wait": "Attendez s'il vous plait..",
|
||||
"filter": "Filtrer",
|
||||
"not_found": "Introuvable",
|
||||
"nothing_found": "Rien n'a été trouvé",
|
||||
"expand_collapse": "Agrandir/Réduire",
|
||||
"options": "Options",
|
||||
"settings": "Paramètres",
|
||||
"about": "À Propos",
|
||||
"meta": "Meta",
|
||||
"permissions": "Permissions",
|
||||
"profile": "Profil",
|
||||
"go_top": "Aller en haut",
|
||||
"help": "Aide",
|
||||
"reference": "référence",
|
||||
"references": "références",
|
||||
"move_up": "Déplacer vers le haut",
|
||||
"move_down": "Déplacer vers le bas",
|
||||
"indent": "Retrait",
|
||||
"outdent": "Retrait extérieur",
|
||||
"default": "Défaut",
|
||||
"no_undo": "Procédez avec prudence car il n'y a pas d'annulation",
|
||||
"show_hide": "Montrer/cacher",
|
||||
"sent": "Envoyer",
|
||||
"everyone": "Tout le monde",
|
||||
"ip": "IP",
|
||||
"event": "Événement",
|
||||
"when": "Quand",
|
||||
"last_seen": "Vue pour la dernière fois",
|
||||
"change": "Changer",
|
||||
"no_access": "Accès interdit",
|
||||
"drag_drop_reorder": "Glisser/déposer pour réordonner",
|
||||
"select": "Selectionner",
|
||||
"locale": "Paramètres régionaux",
|
||||
|
||||
"public": "Publique",
|
||||
"public_explain": "Publique - peut être vue par tout le monde",
|
||||
"protected": "Protégé",
|
||||
"protected_explain": "Protégé - l'accès est limité aux utilisateurs sélectionnés",
|
||||
"personal": "Personnel",
|
||||
"personal_explain": "Personnel - visible uniquement par moi",
|
||||
"label": "Étiquette",
|
||||
"labels": "Étiquettes",
|
||||
"labels_none": "Aucune étiquette",
|
||||
"label_unclassified": "Non-classifié",
|
||||
"draft": "Brouillon",
|
||||
"drafted": "Brouillon",
|
||||
"draft_explain": "Brouillon - doit être approuvé avant publication, pas d'historique de révision",
|
||||
"drafts": "Brouillons",
|
||||
"live": "Direct",
|
||||
"live_explain": "Direct - publié à la création",
|
||||
"archived": "Archivé",
|
||||
"archived_explain": "Archivé - non visible par quiconque",
|
||||
"approved": "Approuvé",
|
||||
"reverted": "Inversé",
|
||||
"published": "Publié",
|
||||
"space": "Espace",
|
||||
"spaces": "Espaces",
|
||||
"category": "Catégorie",
|
||||
"category_explain": "Attribuez des catégories aux documents et décidez qui peut les consulter",
|
||||
"categories": "Catégories",
|
||||
"tag": "Tag",
|
||||
"tags": "Tags",
|
||||
"tag_rules": "Spécifiez jusqu'à {1} tags — minuscules, caractères, chiffres, traits d'union uniquement",
|
||||
"revisions": "Révisions",
|
||||
"versions": "Versions",
|
||||
"version": "Version",
|
||||
"versioned": "Versionné",
|
||||
"versions_explain": "Créez plusieurs versions du même contenu — les utilisateurs peuvent sélectionner la version à afficher",
|
||||
"change_control": "Le contrôle des modifications",
|
||||
"change_control_explain": "Sélectionnez la méthode de contrôle des modifications",
|
||||
"pin": "Épingle",
|
||||
"pinned": "Épinglé",
|
||||
"unpin": "Désépingler",
|
||||
"unpinned": "Désépinglé",
|
||||
"blocks": "Content Blocks",
|
||||
"blocks_explain": "Les blocs de contenu fournissent un contenu réutilisable qui peut être inséré dans n'importe quel document",
|
||||
"block_delete_confirm": "Voulez-vous vraiment supprimer ce bloc de contenu réutilisable ?",
|
||||
"actions": "Actions",
|
||||
"activity": "Activité",
|
||||
"activity_explain": "Rapports sur l'activité des utilisateurs, y compris les ajouts, les vues, les mises à jour, les approbations",
|
||||
"reports": "Raports",
|
||||
"content": "Contenu",
|
||||
"template": "Modèle",
|
||||
"templates": "Modèles",
|
||||
"document": "Document",
|
||||
"documents": "Documents",
|
||||
"attachments": "Pièces jointes",
|
||||
"history": "Historique",
|
||||
"bookmark": "Signet",
|
||||
"bookmarks": "Signets",
|
||||
"bookmark_remove": "Enlever signet",
|
||||
"new": "Nouveau",
|
||||
"copy_link": "Copier lien",
|
||||
"created": "Créer",
|
||||
"markdown": "Markdown accepté",
|
||||
"rename": "Renommer",
|
||||
"status": "Statut",
|
||||
"expiry": "Expiration",
|
||||
"feedback": "Commentaires",
|
||||
"un_categorized": "Non classé",
|
||||
|
||||
"toc": "table des matières",
|
||||
"new_canvas": "Page blanche",
|
||||
"new_template": "Depuis un modèle",
|
||||
"new_import": "Importer un fichier",
|
||||
"new_import_explain1": "Cliquez pour sélectionner des fichiers ou glisser déposer",
|
||||
"new_import_explain2": ".doc, .docx, .md, .markdown",
|
||||
"new_content": "Nouveau contenu",
|
||||
"export_html": "Exporter en HTML",
|
||||
"export_html_explain1": "exportez tout le contenu de l'espace au format HTML ou sélectionnez des catégories.",
|
||||
"export_html_explain2": "Tout le contenu de l'espace sera exporté sous la forme d'un seul fichier HTML auto-inclus.",
|
||||
"import_convert": "En conversion {1}",
|
||||
"import_success": "Conversion réussie {1}",
|
||||
"add_recent": "Ajouté récemment",
|
||||
"update_recent": "Mise à jour récemment",
|
||||
"space_change": "Déplacer dans un nouvel espace",
|
||||
"space_change_prompt": "Sélectionner un espace",
|
||||
"space_new": "Nouvel Espace",
|
||||
"space_name": "Nom de l'espace",
|
||||
"space_name_rules": "Caractères et chiffres uniquement",
|
||||
"space_description": "Description de l'espace",
|
||||
"space_clone": "Cloner l'espace",
|
||||
"space_select": "Sélectionner l'espace",
|
||||
"space_delete": "Supprimer l'espace",
|
||||
"space_delete_prompt": "Veuillez saisir le nom de l'espace pour confirmer",
|
||||
"space_delete_warn": "Cela supprimera tous les documents et modèles de cet espace !",
|
||||
"space_copy": "Copier des modèles, des autorisations, des documents à partir d'un espace existant",
|
||||
"space_copy_template": "Copier les modèles",
|
||||
"space_copy_permission": "Copier les permissions",
|
||||
"space_copy_document": "Copier les documents",
|
||||
"space_empty_state": "Ajouter des documents via + CONTENU",
|
||||
"space_lockout": "Les autorisations de l'espace vous empêchent d'afficher et de créer des documents",
|
||||
"space_invite_message": "Bonjour, je partage l'espace {1} (dans {2}) avec vous afin que nous puissions tous les deux collaborer sur cette documentation.",
|
||||
"protection_none": "Modifications autorisées sans approbation",
|
||||
"protection_lock": "Verrouillé, modifications interdites",
|
||||
"protection_review": "Les modifications doivent être approuvées avant publication",
|
||||
"template_published": "Modèle publié",
|
||||
"block_explain": "Les blocs de contenu fournissent un contenu réutilisable qui peut être inséré dans n'importe quel document",
|
||||
"block_published": "Bloc publié",
|
||||
"upload_attachment": "Charger des pièces jointes",
|
||||
"content_revisions": "Révisions de contenu",
|
||||
"content_revisions_explain": "Examiner les modifications précédentes du contenu et annuler les modifications",
|
||||
"move_documents": "Déplacer des documents",
|
||||
"delete_documents": "Supprimer documents",
|
||||
"feedback_enable": "Activer les commentaires",
|
||||
"feedback_prompt": "Texte de commentaires",
|
||||
"feedback_prompt_hint": "Entrez le texte invitant l'utilisateur à renseigner un commentaire",
|
||||
"feedback_prompt_explain": "Spécifiez le texte qui apparait, par ex. Cela vous a-t-il aidé ? Est-ce que cela a été utile? Avez-vous trouvé ce dont vous aviez besoin ?",
|
||||
"feedback_thanks": "Merci pour les commentaires !",
|
||||
"feedback_help_yes": "Oui, merci !",
|
||||
"feedback_help_no": "Pas vraiment",
|
||||
"likes_prompt": "Cela vous a-t-il aidé ?",
|
||||
"delete_confirm": "Êtes-vous sûr de vouloir supprimer?",
|
||||
"category_assignment_summary": "Attribué à {1} documents et visible par {2} utilisateurs/groupes",
|
||||
"category_no_access": "Vous n'avez pas d'autorisation d'affichage pour cette catégorie",
|
||||
"category_default": "Catégorie par défaut pour le nouveau contenu",
|
||||
"category_default_explain": "S'applique automatiquement aux documents nouvellement créés",
|
||||
"category_delete_confirm": "Voulez-vous vraiment supprimer cette catégorie ?",
|
||||
"category_permissions": "Autorisations de catégorie",
|
||||
"category_permissions_explain": "Sélectionnez qui peut afficher les documents dans la catégorie",
|
||||
"category_none": "Cet espace n'a pas encore de catégories",
|
||||
|
||||
"approval_anybody": "Approbation requise de n'importe approbateur",
|
||||
"approval_majority": "Approbation avec majorité requise des approbateurs",
|
||||
"approval_unanimous": "Approbation unanime requise de tous les approbateurs",
|
||||
"approval_pending": "Modifications en attente",
|
||||
"approval_awaiting": "En attente d'approbation",
|
||||
"protection_type_open": "Libre",
|
||||
"protection_type_protected": "Protégé",
|
||||
"protection_type_locked": "Verrouillé",
|
||||
"doc_request_contribution": "Demande de contribution",
|
||||
"doc_request_feedback": "Demande de retour/commentaires",
|
||||
"doc_request_read": "Demande de lecture",
|
||||
"doc_request_publication": "Demande de publication",
|
||||
"doc_request_approval": "Demande d'approbation",
|
||||
"doc_withdraw_approval": "Demande de retrait",
|
||||
"doc_withdraw_approval_reason": "Explication",
|
||||
"doc_withdraw_approval_reason_explain": "Note utile expliquant la raison, par ex. corrections, ajouts",
|
||||
"doc_review_publish": "S'il vous plaît pouvez-vous examiner et approuver les modifications.",
|
||||
"doc_review_discard": "Je souhaite retirer cette demande d'approbation.",
|
||||
"doc_contribution_pending": "Vous avez une modification en attente",
|
||||
"doc_contribution_under_review": "Votre demande d'approbation est en cours d'examen",
|
||||
"doc_contribution_rejected": "Votre modification a été rejetée",
|
||||
"doc_contribution_review": "Examiner les modifications ({1})",
|
||||
"doc_change_status": "{1} modification(s) en cours, {2} en attente d'examen, {3} rejetées",
|
||||
"doc_approve_reject": "Approuver/rejeter les modifications",
|
||||
"doc_approve_method": "Méthode d'approbation",
|
||||
"doc_approve_status": "Statut d'approbation",
|
||||
"doc_approver_status": "{1} approbations et {2} rejets avec {3} approuveurs impliqués dans cet examen",
|
||||
"doc_publish": "Pouvez-vous déplacer ce document de Brouillon à Publié ? Nous sommes prêts à le publier !",
|
||||
"doc_category_explain": "Attribuer une ou plusieurs catégories pour aider à organiser le contenu dans cet espace",
|
||||
"doc_action_request_ask": "Demander",
|
||||
"doc_action_request_to": "à",
|
||||
"doc_action_request_by": "par",
|
||||
"revision_none": "Aucune révision effectuée",
|
||||
"revision_restore": "Restaurer la section",
|
||||
"revision_restore_confirm": "Êtes-vous sûr de vouloir restaurer cette révision ?",
|
||||
"template_save": "Enregistrer en tant que modèle",
|
||||
"template_name_explain": "Un bon nom de modèle exprime le type de document",
|
||||
"template_desc_explain": "Expliquez le cas d'utilisation de ce modèle",
|
||||
"print_explain": "Imprimer tout le contenu ou sélectionner des sections",
|
||||
"doc_delete_confirm": "Êtes-vous sûr de vouloir supprimer ce document ?",
|
||||
"attachment_delete": "Supprimer la pièce jointe",
|
||||
"attachment_delete_confirm": "Êtes-vous sûr de vouloir supprimer cette pièce jointe ?",
|
||||
"link_insert": "Insérer un lien",
|
||||
"link_type_section": "Section",
|
||||
"link_type_section_explain": "Lien vers le contenu de ce document",
|
||||
"link_type_attachment": "Pièce jointe",
|
||||
"link_type_attachment_explain": "Lien vers une pièce jointe dans ce document",
|
||||
"link_type_search": "Rechercher",
|
||||
"link_type_search_explain": "Nom de document, contenu, nom de pièce jointe",
|
||||
"link_type_network": "Réseau",
|
||||
"link_type_network_explain": "Spécifiez l'emplacement du réseau, de l'unité partagée ou du dossier",
|
||||
"link_type_network_example": "par ex. //partage/dossier",
|
||||
"discard_changes": "Ignorer les modifications",
|
||||
"discard_confirm": "Vous avez apporté des modifications - continuer à éditer ou annuler les modifications ?",
|
||||
"share_expire_2": "dans 2 jours",
|
||||
"share_expire_7": "dans 7 jours",
|
||||
"share_expire_14": "dans 14 jours",
|
||||
"share_expire_30": "dans 30 jours",
|
||||
"share_expire_60": "dans 60 jours",
|
||||
"share_expire_90": "dans 90 jours",
|
||||
|
||||
"actions_mine": "Actions attribuées à vous",
|
||||
"actions_none": "Vous n'avez aucune action",
|
||||
"actions_due": "du",
|
||||
"actions_see_note": "lire la note",
|
||||
"actions_mark_complete": "marquer comme terminé",
|
||||
"actions_completed": "terminé",
|
||||
"actions_see_more": "{1} actions terminées →",
|
||||
"actions_requested": "Actions que vous avez attribuées à d'autres",
|
||||
"actions_requested_none": "Vous n'avez effectué aucune demande",
|
||||
"actions_requested_more": "{1} demandes terminées récemment →",
|
||||
"actions_requested_complete": "{1} demandes terminées →",
|
||||
"activity_period": "Période",
|
||||
"activity_filter_past": "Depuis",
|
||||
"activity_filter_days": "Jours",
|
||||
"activity_filter_for": "Pour",
|
||||
"audit_24": "24 heures",
|
||||
"audit_7": "7 jours",
|
||||
"audit_14": "14 jours",
|
||||
"audit_30": "30 jours",
|
||||
"audit_90": "90 jours",
|
||||
"chat_leave_comment": "Laisser un commentaire",
|
||||
"chat_applies_to": "S'applique à",
|
||||
"chat_delete_confirm": "Êtes-vous sûr de vouloir supprimer ce commentaire ?",
|
||||
"chat_reply_delete_confirm": "Êtes-vous sûr de vouloir supprimer cette réponse ?",
|
||||
"doc_secure_share": "Partager via un lien externe sécurisé",
|
||||
"doc_secure_shared_by": "Partagé par",
|
||||
"doc_version_viewed": "Renommer la version",
|
||||
"doc_version_remove": "Annuler la version",
|
||||
"doc_version_create": "Créer une version de document",
|
||||
"doc_version_explain": "Les versions sont attribuées aux documents, où chaque version est un document différent.",
|
||||
"doc_version_label": "Étiquette de version",
|
||||
"doc_version_label_explain": "par exemple 1.0, v1.0, Version 1, 2018.1 Release",
|
||||
"doc_version_this": "Créer une nouvelle version de ce document",
|
||||
"doc_version_select": "ou sélectionnez un autre document",
|
||||
"doc_version_assign": "Attribuer la version à ce document",
|
||||
"doc_version_dropdown": "<attribuer la version à un autre document>",
|
||||
"doc_version_remove_confirm": "Êtes-vous sûr de vouloir supprimer cette version et tout son contenu?",
|
||||
"doc_version_remove_name": "Veuillez confirmer en tapant le nom du document ci-dessous",
|
||||
"doc_version_unversion": "L'opération de dé-versionnement rendra le document indépendant en conservant tout le contenu intact.",
|
||||
"doc_version_unversion_confirm": "Êtes-vous sûr de vouloir dé-versionner le document?",
|
||||
"archived_content": "Contenu archivé",
|
||||
"archived_content_explain": "Marquer le contenu archivé comme publié",
|
||||
"unarchive_content": "Dé-archiver le contenu",
|
||||
|
||||
"document_permissions": "Permissions du document",
|
||||
"space_permissions": "Permissions de l'espace",
|
||||
"space_permissions_explain": "Attribuer des permissions aux utilisateurs ou aux groupes et inviter de nouveaux utilisateurs à cet espace",
|
||||
"space_permission_view": "Voir",
|
||||
"space_permission_view_explain": "Voir le contenu de cet espace",
|
||||
"space_permission_manage": "Gérer",
|
||||
"space_permission_manage_explain": "Gérer tous les aspects de l'espace, à l'exception de la suppression",
|
||||
"space_permission_owner": "Propriétaire",
|
||||
"space_permission_owner_explain": "Gérer et supprimer l'espace",
|
||||
"space_permission_doc_create": "Créer",
|
||||
"space_permission_doc_create_explain": "Peut créer de nouveaux documents dans cet espace",
|
||||
"space_permission_doc_edit": "Modifier",
|
||||
"space_permission_doc_edit_explain": "Peut changer le contenu des documents",
|
||||
"space_permission_doc_delete": "Supprimer",
|
||||
"space_permission_doc_delete_explain": "Peut supprimer des documents de l'espace",
|
||||
"space_permission_doc_move": "Déplacer",
|
||||
"space_permission_doc_move_explain": "Peut déplacer des documents de cet espace vers un autre espace",
|
||||
"space_permission_doc_copy": "Copier",
|
||||
"space_permission_doc_copy_explain": "Peut dupliquer des documents",
|
||||
"space_permission_doc_template": "Modèles",
|
||||
"space_permission_doc_template_explain": "Peut créer et publier des modèles de document",
|
||||
"space_permission_doc_approval": "Approbation",
|
||||
"space_permission_doc_approval_explain": "Peut (1) approuver ou rejeter les modifications du document ; (2) déplacer les documents du brouillon à la version publique",
|
||||
"space_permission_doc_draft": "Brouillon",
|
||||
"space_permission_doc_draft_explain": "Peut afficher et travailler sur les documents marqués en tant que brouillon",
|
||||
"space_permission_doc_version": "Versions",
|
||||
"space_permission_doc_version_explain": "Peut créer une version du document et les lier ensemble",
|
||||
"space_permission_add_user": "Ajouter des utilisateurs à cet espace",
|
||||
"space_permission_invite_user": "Inviter des utilisateurs à cet espace",
|
||||
"space_permission_invite_explain": "Séparer les adresses e-mail multiples par des virgules",
|
||||
|
||||
"section_insert": "Insérer une section",
|
||||
"section_insert_here": "Insérer une section ici",
|
||||
"section_copy_explain": "Cette section et toutes les sections imbriquées seront copiées dans le document sélectionné.",
|
||||
"section_move_explain": "Cette section et toutes les sections imbriquées seront déplacées dans le document sélectionné.",
|
||||
"section_delete": "Êtes-vous sûr de vouloir supprimer cette section ?",
|
||||
"section_delete_children": "Supprimer également les sections enfant",
|
||||
"section_publish": "Publier le bloc de contenu réutilisable",
|
||||
"section_publish_name_explain": "Fournir un titre court pour le bloc de contenu réutilisable",
|
||||
"section_publish_desc_explain": "Description courte pour aider les autres à comprendre le bloc de contenu réutilisable",
|
||||
"section_airtable": "Airtable",
|
||||
"section_airtable_explain": "Partie tableur, partie base de données et entièrement flexible (https://airtable.com)",
|
||||
"section_airtable_code": "Code d'intégration Airtable",
|
||||
"section_code_tip": "Nom concis qui décrit le code",
|
||||
"section_drawio": "Diagrams.net",
|
||||
"section_drawio_explain": "Pour faire des diagrammes de flux, des diagrammes de processus, des organigrammes, UML, des diagrammes ER, des diagrammes de réseau et bien plus encore (https://www.diagrams.net)",
|
||||
"section_iframe": "iFrame",
|
||||
"section_iframe_explain": "Intégrer un iFrame",
|
||||
"section_iframe_code": "Code d'intégration iFrame",
|
||||
"section_gemini": "Gemini",
|
||||
"section_gemini_explain": "Logiciel de gestion de tickets d'entreprise et d'assistance Gemini (https://www.countersoft.com)",
|
||||
"section_gemini_url": "URL Gemini",
|
||||
"section_gemini_url_explain": "par ex. https://helpdesk.countersoft.com",
|
||||
"section_gemini_key": "Clé API (du profil utilisateur)",
|
||||
"section_gemini_workspace": "Espace de travail",
|
||||
"section_jira": "Jira Software",
|
||||
"section_jira_explain": "Jira fournit une gestion des incidents et un logiciel agil",
|
||||
"section_jira_admin": "Votre administrateur de la communauté Documize doit fournir les détails de connexion Jira avant l'utilisation.",
|
||||
"section_jira_no_auth": "Connecteur Jira non authentifié",
|
||||
"section_papertrail": "Papertrail",
|
||||
"section_papertrail_explain": "Afficher vos journaux basé sur le cloud (https://papertrailapp.com)",
|
||||
"section_papertrail_key": "Clé API de Papertrail",
|
||||
"section_papertrail_search": "Requête de recherche",
|
||||
"section_papertrail_search_explain": "Déterminez les entrées de journal que vous voulez afficher, par exemple bob OU (\"exemple de phrase\" ET sally)",
|
||||
"section_papertrail_max": "Résultats maximums",
|
||||
"section_papertrail_max_explain": "Combien d'entrées de journal voulez-vous afficher ?",
|
||||
"section_papertrail_group": "Groupe",
|
||||
"section_papertrail_group_explain": "Groupe Papertrail facultatif",
|
||||
"section_pdf": "Visualiseur PDF",
|
||||
"section_pdf_upload_explain": "Le premier PDF téléchargé sera utilisé",
|
||||
"section_pdf_height": "Hauteur de l'aperçu",
|
||||
"section_pdf_height_explain": "Quelle est la hauteur de l'aperçu du PDF ?",
|
||||
"section_pdf_start": "Page de démarrage",
|
||||
"section_pdf_start_explain": "La première page à afficher",
|
||||
"section_pdf_sidebar": "Barre latérale",
|
||||
"section_pdf_sidebar_explain": "En option, définir le contenu de la barre latérale",
|
||||
"section_pdf_sidebar_none": "Aucun",
|
||||
"section_pdf_sidebar_bookmark": "Signets",
|
||||
"section_pdf_sidebar_thumbnail": "Vignettes",
|
||||
"section_plantuml": "PlantUML",
|
||||
"section_plantuml_explain": "Créez des diagrammes UML à partir d'un langage de texte simple (http://plantuml.com)",
|
||||
"section_plantuml_link": "Diagramme PlantUML",
|
||||
"section_plantuml_type_sequence": "Séquence",
|
||||
"section_plantuml_type_usecase": "Cas d'utilisation",
|
||||
"section_plantuml_type_class": "Classe",
|
||||
"section_plantuml_type_activity": "Activité",
|
||||
"section_plantuml_type_activity2": "Activité (nouvelle syntaxe)",
|
||||
"section_plantuml_type_component": "Composant",
|
||||
"section_plantuml_type_state": "État",
|
||||
"section_tabular_import_csv": "Importer CSV",
|
||||
"section_tabular_csv": "CSV vers tableau",
|
||||
"section_tabular_warn": "Remarque : les données existantes de la table seront remplacées",
|
||||
"section_tabular_paste": "Coller les données CSV",
|
||||
"section_tabular_format": "Les délimiteurs courants sont pris en charge",
|
||||
"section_tabular_first_row": "Première ligne d'en-tête",
|
||||
"section_tabular_first_row_explain": "Activer si la première ligne contient des en-têtes",
|
||||
"section_trello": "Trello",
|
||||
"section_trello_explain": "Trello est la manière visuelle de gérer vos projets et d'organiser tout (https://trello.com)",
|
||||
"section_trello_none": "Vous n'avez aucun tableau d'équipe à partager - les tableaux personnels ne sont jamais affichés",
|
||||
"section_trello_admin": "L'administrateur de votre Communauté Documize doit configurer Trello avant l'utilisation.",
|
||||
"section_trello_board": "Tableau",
|
||||
"section_trello_list": "Liste",
|
||||
|
||||
"login_cas": "Authentification avec CAS...",
|
||||
"login_cass_error": "Échec d'authentification CAS",
|
||||
"login_keycloak": "Authentification avec Keycloak...",
|
||||
"login_keycloak_error": "Échec d'authentification Keycloak",
|
||||
"login_invalid": "Informations d'identification non valides",
|
||||
"forgot_password": "Mot de passe oublié ?",
|
||||
"reset_password": "Réinitialiser le mot de passe",
|
||||
"reset_password_next": "Merci. Vérifiez votre boîte email pour les instructions.",
|
||||
"password_strong": "Choisissez un mot de passe fort",
|
||||
"password_match": "Les mots de passe doivent correspondre",
|
||||
"welcome": "Bienvenue sur Documize",
|
||||
"welcome_explain": "Configurons votre compte et commençons",
|
||||
"profile_explain": "Gérez votre profil et mot de passe",
|
||||
"search_hint": "mots-clés, tags",
|
||||
"search_too_short": "Votre requête de recherche est trop courte",
|
||||
"search_doc_name": "Nom du document",
|
||||
"search_doc_content": "Contenu du document",
|
||||
"search_tag_name": "Nom du tag",
|
||||
"search_attachment_name": "Nom de la pièce jointe",
|
||||
"search_example_title": "Exemples de requête",
|
||||
"search_explain": "Trouvez du contenu à l'aide de mots-clés et d'opérateurs",
|
||||
"search_example1": "Afficher les résultats qui contiennent au moins l'un des deux mots",
|
||||
"search_example2": "Afficher les résultats qui contiennent les deux mots",
|
||||
"search_example3": "Afficher les résultats qui contiennent le mot \"pomme\", mais classer en premier les lignes qui contiennent également \"macintosh\"",
|
||||
"search_example4": "Afficher les résultats qui contiennent le mot \"pomme\", mais pas \"macintosh\"",
|
||||
"search_example5": "Afficher les résultats qui contiennent les mots \"pomme\" et \"tarte\", ou \"pomme\" et \"strudel\" (dans n'importe quel ordre), mais classer \"tarte pomme\" plus haut que \"strudel pomme\"",
|
||||
"search_example6": "Afficher les résultats qui contiennent des mots tels que \"pomme\", \"pommes\", \"compote de pommes\", ou \"pomme\"",
|
||||
"search_example7": "Afficher les résultats qui contiennent l'expression exacte \"certains mots\" (par exemple, les lignes qui contiennent \"certains mots intéressant\" mais pas \"certains autres mots\")",
|
||||
"search_example8": "Afficher les résultats qui contiennent soit le mot",
|
||||
"search_example9": "Afficher les résultats qui ont \"google\", soit \"apple\" ou \"microsoft\", mais pas \"ibm\"",
|
||||
"search_example10": "Afficher les résultats qui contiennent des mots qui commencent par \"apple\", tels que \"compote de pommes\" ou \"pomme d'amour\"",
|
||||
"space_density_complete": "Complet",
|
||||
"space_density_comfort": "Confort",
|
||||
"space_density_compact": "Compact",
|
||||
|
||||
"backup_explain1": "Documize Community est une application multi-tenant qui permet à 'tech.mycompany.com' et 'sales.mycompany.com' de fonctionner en utilisant le même exécutable/base de données. En tant qu'administrateur global de Documize Community, vous effectuerez une sauvegarde complète de tout le système pour tous les tenant. L'administrateur tenant de Documize Community peut se connecter pour effectuer une sauvegarde de niveau tenant (par exemple marketing.mycompany.com).",
|
||||
"backup_explain2": "Documize Community est une application multi-tenant qui permet à 'tech.mycompany.com' et 'sales.mycompany.com' de fonctionner en utilisant le même exécutable/base de données. En tant qu'administrateur global de Documize Community, vous effectuerez une sauvegarde complète de tout le système pour tous les tenant. En tant qu'administrateur tenant de Documize Community, vous pouvez effectuer une sauvegarde de niveau tenant (par exemple marketing.mycompany.com).",
|
||||
"backup_explain3": "Il peut prendre plusieurs minutes pour compléter le processus de sauvegarde - veuillez être patient pendant que l'opération de sauvegarde est en cours.",
|
||||
"backup_retain": "Conserver le fichier de sauvegarde sur le serveur",
|
||||
"backup_running": "Sauvegarde en cours, veuillez patienter...",
|
||||
"backup_tenant": "Sauvegarder le tenant",
|
||||
"backup_system": "Sauvegarder le système",
|
||||
"backup_failed": "Sauvegarde échouée - veuillez vérifier les journaux de serveur",
|
||||
"backup_success": "Sauvegarde réussie",
|
||||
"backup_start": "Démarrer la sauvegarde",
|
||||
"backup_run": "Exécuter la sauvegarde",
|
||||
"restore_explain1": "La restauration à partir d'une sauvegarde système ne doit être effectuée que sur une base de données Documize Community vide.",
|
||||
"restore_explain2": "L'opération de restauration recréera les utilisateurs, les groupes, les autorisations, les espaces, les catégories et le contenu.",
|
||||
"restore_explain3": "Il peut prendre plusieurs minutes pour compléter le processus de restauration - veuillez être patient pendant que l'opération de restauration est en cours.",
|
||||
"restore_select_file": "Choisir le fichier de sauvegarde",
|
||||
"restore_running": "Veuillez patienter, restauration en cours...",
|
||||
"restore_failed": "La restauration a échoué -- veuillez vérifier les journaux du serveur",
|
||||
"restore_success": "Restauration terminée -- redémarrez votre navigateur et connectez-vous",
|
||||
"restore_confirm": "Confirmer la restauration",
|
||||
"restore_confirm_input": "Veuillez taper RESTORE pour commencer le processus",
|
||||
"restore_warn": "Vous ne devriez restaurer qu'une instance vide de Documize Community",
|
||||
"changelog_available": "Mise à jour du produit disponible",
|
||||
"changelog_guidance": "Pour mettre à jour, remplacez le binaire existant et redémarrez Documize Community.",
|
||||
"customize_name": "Nom du site",
|
||||
"customize_name_explain": "Fournir un titre court pour cette instance de Documize Community",
|
||||
"customize_message": "Message du site",
|
||||
"customize_message_explain": "Fournir un court message expliquant cette instance de Documize Community",
|
||||
"customize_theme": "Thème du site",
|
||||
"customize_logo": "Logo du site",
|
||||
"customize_logo_default": "Utiliser par défaut",
|
||||
"customize_logo_upload": "Télécharger personnalisé",
|
||||
"customize_logo_explain": "Vous pouvez choisir de télécharger un petit logo (par exemple 64px x 64px)",
|
||||
"customize_subdomain": "Sous-domaine de l'URL du site",
|
||||
"customize_subdomain_explain": "Si vous hébergez sur 'docs.example.org', alors la valeur du sous-domaine devrait être définie sur 'docs'",
|
||||
"customize_anon": "Les espaces publics visibles par les utilisateurs anonymes",
|
||||
"customize_anon_explain": "Partager le contenu avec les visiteurs du site non authentifiés",
|
||||
"customize_conversion_url": "URL du service de conversion",
|
||||
"customize_conversion_explain": "Point de terminaison pour gérer l'import/export",
|
||||
"customize_tags": "Nombre maximum de tags par document",
|
||||
"customize_tags_explain": "Combien de tags peuvent être attribués à un document (entre 3 et 10 tags)",
|
||||
"integration_jira_url": "URL",
|
||||
"integration_jira_url_explain": "Nom de domaine qualifié pour votre instance Jira, par exemple http://jira.example.org",
|
||||
"integration_jira_username": "Nom d'utilisateur",
|
||||
"integration_jira_username_explain": "Votre nom d'utilisateur / email de connexion Jira",
|
||||
"integration_jira_password": "Mot de passe",
|
||||
"integration_jira_password_explain": "Fournir un jeton API si vous utilisez Atlassian Cloud ou un mot de passe lorsque vous hébergez Jira vous-même",
|
||||
"integration_trello_appkey": "Clé d'application",
|
||||
"search_reindex": "Il peut prendre jusqu'à 30 minutes pour reconstruire l'index de recherche.",
|
||||
"search_reindex_rebuild": "Reconstruire",
|
||||
"search_reindex_start": "Démarrage du processus de ré-indexation de la recherche",
|
||||
"search_reindex_finish": "Ré-indexation de la recherche terminée",
|
||||
"smtp_host": "Hôte",
|
||||
"smtp_host_explain": "par exemple my.host.com",
|
||||
"smtp_port": "Port",
|
||||
"smtp_port_explain": "par exemple 587",
|
||||
"smtp_username": "Nom d'utilisateur",
|
||||
"smtp_username_explain": "par exemple nom d'utilisateur de connexion pour le serveur SMTP",
|
||||
"smtp_password": "Mot de passe",
|
||||
"smtp_password_explain": "par exemple mot de passe de connexion pour le serveur SMTP",
|
||||
"smtp_sender_email": "Email de l'expéditeur",
|
||||
"smtp_sender_email_explain": "par exemple, user@example.org",
|
||||
"smtp_sender_name": "Nom de l'expéditeur",
|
||||
"smtp_sender_name_explain": "par exemple, Documize",
|
||||
"smtp_fqdn": "Nom de domaine qualifié de plein droit du serveur d'envoi",
|
||||
"smtp_fqdn_explain": "(facultatif) SMTP peut nécessiter un nom de domaine valide, par exemple, docs.example.org",
|
||||
"smtp_anon_auth": "Authentification anonyme (ignorer les informations d'identification)",
|
||||
"smtp_base64": "Encodez les informations d'identification en Base64",
|
||||
"smtp_ssl": "Utiliser SSL",
|
||||
"smtp_save_test": "Enregistrer & Tester",
|
||||
"smtp_sent_test_email": "Envoi d'un e-mail de test à vous",
|
||||
"smtp_missing": "Paramètres de serveur de courrier manquants",
|
||||
"space_admin_export": "Exporter tout le contenu",
|
||||
"space_admin_export_running": "Export en cours....",
|
||||
"space_admin_make_owner": "Me nommer propriétaire",
|
||||
"space_admin_empty": "Il n'y a pas d'espaces partagés à gérer",
|
||||
"space_admin_delete_title": "Suppression de l'espace",
|
||||
"space_admin_delete_check": "Êtes-vous sûr de vouloir supprimer cet espace et tous les documents?",
|
||||
"space_admin_confirm": "Veuillez taper le nom de l'espace pour confirmer",
|
||||
"space_admin_confirm_explain": "Cela supprimera tous les documents et les modèles dans cet espace!",
|
||||
"label_add": "Ajouter une étiquette",
|
||||
"label_update": "Mettre à jour l'étiquette",
|
||||
"label_delete": "Supprimer l'étiquette",
|
||||
"label_delete_confirm": "Êtes-vous sûr de vouloir supprimer l'étiquette {1} ?",
|
||||
"user_admin_add": "Ajouter des utilisateurs",
|
||||
"user_admin_bulk": "Téléchargement en bloc",
|
||||
"user_admin_bulk_format": "Liste délimitée par des virgules: prénom, nom, email",
|
||||
"group_add": "Ajouter un groupe",
|
||||
"group_name_explain": "Entrez le nom du groupe, par exemple, les gestionnaires, les développeurs, l'équipe Acme",
|
||||
"group_member_add": "Ajouter un membre",
|
||||
"group_member_remove": "Supprimer un membre",
|
||||
"group_delete": "Supprimer le groupe",
|
||||
"group_delete_confirm": "Êtes-vous sûr de vouloir supprimer ce groupe ?",
|
||||
"group_delete_name": "Veuillez taper le nom du groupe pour confirmer",
|
||||
"group_delete_name_explain": "Cela supprimera les informations sur l'appartenance au groupe et les autorisations associées",
|
||||
"group_none": "Aucun groupe",
|
||||
"group_edit": "Modifier le groupe",
|
||||
"find_user": "Trouver des utilisateurs",
|
||||
"find_user_syntax": "Rechercher prénom, nom, email",
|
||||
"user_max_display": "Nombre maximum d'utilisateurs à afficher",
|
||||
"user_assign_group": "Assigner des groupes d'utilisateurs",
|
||||
"user_delete_confirm": "Êtes-vous sûr de vouloir supprimer l'utilisateur {1} ?",
|
||||
"user_selected_delete_confirm": "Êtes-vous sûr de vouloir supprimer les utilisateurs sélectionnés ?",
|
||||
"user_delete": "Supprimer l'utilisateur",
|
||||
"permission_spaces": "Espaces",
|
||||
"permission_spaces_explain": "Peut ajouter des espaces, personnels ou partagés avec d'autres",
|
||||
"permission_visible": "Visible",
|
||||
"permission_visible_explain": "Peut voir les noms des utilisateurs et des groupes, peut désactiver pour les utilisateurs externes tels que les clients/partenaires",
|
||||
"permission_admin": "Admin",
|
||||
"permission_admin_explain": "Peut gérer tous les aspects de la communauté Documize, comme cette page",
|
||||
"permission_analytics": "Analytiques",
|
||||
"permission_analytics_explain": "Peut voir les rapports analytiques",
|
||||
"permission_active": "Actif",
|
||||
"permission_active_explain": "Peut se connecter et utiliser la communauté Documize",
|
||||
"auth_role_space": "Peut créer des espaces",
|
||||
"auth_disable_logout": "Désactiver la déconnexion",
|
||||
"auth_dual_login": "Connexion double",
|
||||
"auth_dual_login_explain": "Permet la connexion via LDAP et courrier électronique/mot de passe régulier (utile pour tester LDAP)",
|
||||
"auth_email_password": "Courrier électronique/mot de passe intégré",
|
||||
"auth_connect_keycloak": "Se connecter au serveur d'authentification",
|
||||
"auth_connect_ldap": "Se connecter à LDAP/Active Directory",
|
||||
"auth_connect_cas": "Se connecter au serveur d'authentification central",
|
||||
"auth_keycloak_running": "Synchronisation d'utilisateur Keycloak en cours...",
|
||||
"auth_keycloak_sync": "Synchroniser avec Keycloak",
|
||||
"auth_ldap_running": "Synchronisation d'utilisateur LDAP en cours...",
|
||||
"auth_ldap_sync": "Synchroniser avec LDAP",
|
||||
"auth_keycloak_url": "URL du serveur Keycloak",
|
||||
"auth_keycloak_realm": "Royaume Keycloak",
|
||||
"auth_keycloak_pk": "Clé publique du royaume Keycloak",
|
||||
"auth_keycloak_pk_explain": "Copier la clé RSA publique à partir des paramètres du royaume > Clés",
|
||||
"auth_keycloak_oidc": "ID client Keycloak OIDC",
|
||||
"auth_keycloak_group": "ID de groupe Keycloak (optionnel)",
|
||||
"auth_keycloak_group_explain": "Si vous souhaitez synchroniser les utilisateurs dans un groupe particulier (par exemple, 'Utilisateurs de la communauté Documize'), fournissez l'ID du groupe (par exemple, 511d8b61-1ec8-45f6-bc8d-5de64d54c9d2)",
|
||||
"auth_keycloak_username": "Nom d'utilisateur Keycloak",
|
||||
"auth_keycloak_username_explain": "Utilisé pour se connecter à Keycloak et synchroniser les utilisateurs avec la communauté Documize (créer un utilisateur sous le royaume Maître et attribuer le rôle 'view-users' contre le royaume spécifié ci-dessus)",
|
||||
"auth_keycloak_password": "Mot de passe Keycloak",
|
||||
"auth_keycloak_password_explain": "Utilisé pour se connecter à Keycloak et synchroniser les utilisateurs avec la communauté Documize",
|
||||
"auth_ldap_server": "Serveur LDAP",
|
||||
"auth_ldap_server_explain": "Adresse IP ou hôte, par exemple ldap.example.org, 127.0.0.1",
|
||||
"auth_ldap_port": "Port du serveur LDAP",
|
||||
"auth_ldap_port_explain": "Numéro de port, par exemple 389",
|
||||
"auth_ldap_base": "DN de base",
|
||||
"auth_ldap_base_explain": "Point de départ pour les filtres de recherche, par exemple ou = utilisateurs, dc = example, dc = com",
|
||||
"auth_ldap_bind": "DN de liaison",
|
||||
"auth_ldap_bind_explain": "Informations d'identification pour le serveur LDAP",
|
||||
"auth_ldap_password": "Mot de passe de liaison",
|
||||
"auth_ldap_filter_user": "Filtre d'utilisateur",
|
||||
"auth_ldap_filter_user_explain1": "Filtre de recherche pour trouver des utilisateurs, par exemple (|(objectClass=person)(objectClass=user)(objectClass=inetOrgPerson))",
|
||||
"auth_ldap_filter_user_explain2": "Spécifiez le filtre d'utilisateur et / ou le filtre de groupe",
|
||||
"auth_ldap_filter_group": "Filtre de groupe",
|
||||
"auth_ldap_filter_group_explain": "Filtre de recherche pour trouver des utilisateurs via des groupes, par exemple (&(objectClass=group)(|(cn=ship_crew)(cn=admin_staff)))",
|
||||
"auth_ldap_rdn": "Attribut d'utilisateur RDN",
|
||||
"auth_ldap_rdn_explain1": "Attribut de nom d'utilisateur/identifiant, par exemple uid dans LDAP, sAMAccountName dans Active Directory",
|
||||
"auth_ldap_rdn_explain2": "Attributs utilisateur utilisés pour récupérer les données lors de l'utilisation du filtre utilisateur",
|
||||
"auth_ldap_firstname": "Attribut utilisateur Prénom",
|
||||
"auth_ldap_firstname_explain": "Attribut prénom, par exemple givenName",
|
||||
"auth_ldap_lastname": "Attribut utilisateur Nom de famille",
|
||||
"auth_ldap_lastname_explain": "Attribut nom de famille, par exemple sn",
|
||||
"auth_ldap_email": "Attribut utilisateur Email",
|
||||
"auth_ldap_email_explain": "Attribut email, par exemple mail",
|
||||
"auth_ldap_group": "Attribut de groupe Membre",
|
||||
"auth_ldap_group_explain1": "Attribut qui identifie un membre de groupe individuel, par exemple member ou uniqueMember",
|
||||
"auth_ldap_group_explain2": "Attributs de groupe utilisés pour récupérer les données lors de l'utilisation du filtre de groupe",
|
||||
"auth_ldap_preview": "Aperçu LDAP",
|
||||
"auth_ldap_preview_result": "Connexion réussie, {1} utilisateurs trouvés.",
|
||||
"auth_ldap_preview_error": "Impossible de se connecter",
|
||||
"auth_cas_url": "URL du serveur CAS",
|
||||
"auth_cas_url_explain": "par exemple http://localhost:8888/auth",
|
||||
"auth_cas_back_url": "URL CAS de Documize",
|
||||
"auth_cas_back_url_explain": "par exemple http://Documize-URL/auth/cas",
|
||||
"administration": "Administration",
|
||||
"admin_general": "Général",
|
||||
"admin_general_explain": "Options pour vous aider à personnaliser Documize Community",
|
||||
"admin_user_management": "Gestion des utilisateurs",
|
||||
"admin_user_management_explain": "Gérer les informations de base, les mots de passe et les autorisations",
|
||||
"admin_user_groups": "Groupes d'utilisateurs",
|
||||
"admin_user_groups_explain": "Définir des groupes pour une gestion plus facile des utilisateurs et des autorisations",
|
||||
"admin_integrations": "Intégrations",
|
||||
"admin_integrations_explain": "Activer et configurer les intégrations tierces",
|
||||
"admin_mail_server": "Serveur de courrier",
|
||||
"admin_mail_server_explain": "Spécifier les détails du serveur de courrier requis pour envoyer des invitations d'utilisateur et des emails de notification",
|
||||
"admin_audit_log": "Journal d'audit",
|
||||
"admin_backup": "Sauvegarde & Restauration",
|
||||
"admin_backup_explain": "Exporter tout le contenu dans un seul fichier zip autonome",
|
||||
"admin_billing": "Facturation",
|
||||
"admin_changelog": "Journal des modifications",
|
||||
"admin_auth_explain": "Choisir le fournisseur d'authentification d'utilisateur - Documize, Redhat Keycloak, LDAP/AD, Central Authentication Server",
|
||||
"admin_spaces_explain": "Supprimer des espaces, prendre la propriété des espaces partagés et orphelins",
|
||||
"admin_labels_explain": "Regrouper et naviguer dans les espaces avec des étiquettes visuelles",
|
||||
"admin_search_explain": "Reconstruire l'index de recherche",
|
||||
"setup_default_message": "L'instance de Documize Community contient toutes nos documentations",
|
||||
"get_in_touch": "Entrer en contact",
|
||||
"product_feedback": "Avez-vous une idée de produit, une suggestion ou un commentaire?",
|
||||
"product_news": "Nouvelles du produit",
|
||||
"product_news_explain": "Dernières nouvelles et mises à jour du produit",
|
||||
"product_update": "Mise à jour disponible",
|
||||
"product_whats_new": "Quoi de neuf",
|
||||
"product_activation_key_missing": "Clé d'activation manquante",
|
||||
"account_update": "Mettre à jour le compte",
|
||||
"404": "Oups ! Cette page n'a pas pu être trouvée.",
|
||||
"404_explain": "Peut-être que le contenu que vous recherchez n'est plus disponible?",
|
||||
"close_account": "Veuillez fermer mon compte Documize.",
|
||||
"third_party": "La communauté Documize utilise des bibliothèques et des composants open source provenant de tiers.",
|
||||
|
||||
"server_ldap_error1": "Erreur : saut de la synchronisation de l'utilisateur avec LDAP car ce n'est pas l'option configurée",
|
||||
"server_ldap_error2": "Erreur : impossible de lire les données de configuration LDAP",
|
||||
"server_ldap_error3": "Erreur : impossible de récupérer les utilisateurs LDAP: {1}",
|
||||
"server_ldap_complete": "Synchronisation terminée avec le serveur LDAP",
|
||||
"server_ldap_summary": "La synchronisation LDAP a trouvé {1} utilisateurs, {2} nouveaux utilisateurs ajoutés, {3} utilisateurs avec des données manquantes ignorés",
|
||||
"server_keycloak_error1": "Erreur : saut de la synchronisation de l'utilisateur avec Keycloak car ce n'est pas l'option configurée",
|
||||
"server_keycloak_error2": "Erreur : impossible de lire les données de configuration Keycloak",
|
||||
"server_keycloak_error3": "Erreur : impossible de récupérer les utilisateurs Keycloak: {1}",
|
||||
"server_keycloak_summary": "La synchronisation Keycloak a trouvé {1} utilisateurs, {2} nouveaux utilisateurs ajoutés, {3} utilisateurs avec des données manquantes ignorés",
|
||||
"server_smtp_success": "E-mail envoyé avec succès",
|
||||
"server_smtp_test_subject": "Test SMTP de la communauté Documize",
|
||||
"server_smtp_test_body": "Il s'agit d'un email de test de la communauté Documize en utilisant les paramètres SMTP actuels.",
|
||||
"server_error_user": "Erreur : impossible de récupérer les utilisateurs",
|
||||
"server_error_org": "Erreur : impossible de récupérer l'enregistrement de l'organisation",
|
||||
|
||||
"mail_template_click_here": "Cliquez ici",
|
||||
"mail_template_sender": "Votre collègue",
|
||||
"mail_template_approval": "{1} vous a accordé le rôle d'approbation de document",
|
||||
"mail_template_approval_explain": "Vous êtes invité à approuver toutes les modifications apportées au document suivant :",
|
||||
"mail_template_password": "Votre mot de passe temporaire :",
|
||||
"mail_template_user_invite": "{1} vous a invité à rejoindre la communauté Documize",
|
||||
"mail_template_user_existing": "{1} vous a invité à rejoindre leur compte de la communauté Documize",
|
||||
"mail_template_reset_password": "Votre demande de réinitialisation de mot de passe pour la communauté Documize",
|
||||
"mail_template_shared": "{1} a partagé l'espace {2} avec vous",
|
||||
"mail_template_invited": "{1} vous a invité à partager l'espace {2} sur la communauté Documize",
|
||||
"mail_template_approval_request": "{1} a demandé l'approbation des modifications de document",
|
||||
"mail_template_approval_request_explain": "Veuillez approuver les modifications apportées au document intitulé {1}",
|
||||
"mail_template_approval_withdraw": "{1} a retiré sa demande d'approbation des modifications de document",
|
||||
"mail_template_approval_withdraw_explain": "{1} La demande d'approbation a été retirée pour le document",
|
||||
"mail_template_publish_explain": "Vous pouvez publier le document {1} en changeant son statut de Brouillon à Publié.",
|
||||
"mail_template_reviewer": "Revue des modifications de document effectué par {1}",
|
||||
"mail_template_approval_1": "Votre modification n'a pas été publiée car aucun examinateur n'a approuvé la modification.",
|
||||
"mail_template_approval_2": "Votre modification n'a pas été publiée car la majorité des examinateurs n'ont pas approuvé la modification.",
|
||||
"mail_template_approval_3": "Votre modification n'a pas été publiée car l'approbation unanime n'a pas été obtenue.",
|
||||
"mail_template_approval_4": "Votre modification a été publiée car un examinateur a approuvé la modification.",
|
||||
"mail_template_approval_5": "Votre modification a été publiée car la majorité des examinateurs ont approuvé la modification.",
|
||||
"mail_template_approval_6": "Votre modification a été publiée car l'approbation unanime a été obtenue.",
|
||||
"mail_template_approval_7": "Votre modification est toujours en cours d'examen et nécessite l'approbation d'un autre examinateur.",
|
||||
"mail_template_approval_8": "Votre modification est toujours en cours d'examen et nécessite l'approbation de la majorité des examinateurs.",
|
||||
"mail_template_approval_9": "Votre modification est toujours en cours d'examen et nécessite une approbation unanime.",
|
||||
"mail_template_review_outcome": "{1} a examiné votre modification pour le document {2} et a été marqué comme {3}. {4}",
|
||||
"mail_template_action_read": "Veuillez lire le document {1} par {2}.",
|
||||
"mail_template_action_feedback": "Veuillez fournir un commentaire pour le document {1} par {2}.",
|
||||
"mail_template_action_contribute": "Veuillez contribuer au contenu du document {1} par {2}.",
|
||||
"mail_template_publish_request": "{1} a demandé la publication du document",
|
||||
"mail_template_action_assigned": "{1} vous a assigné une action de document",
|
||||
"mail_template_action_done": "{1} a terminé votre action de document",
|
||||
"mail_template_action_read_done": "{1} a lu le document {2} (dû {3})",
|
||||
"mail_template_action_feedback_done": "{1} a fourni un commentaire pour le document {2} (dû {3})",
|
||||
"mail_template_action_contribute_done": "{1} a contribué au contenu du document {2} (dû {3})",
|
||||
"mail_template_share_doc": "{1} a partagé un document avec vous",
|
||||
"mail_template_share_viewed": "{1} a été visionné",
|
||||
"mail_template_feedback_received": "{1} vous a envoyé un commentaire {2}"
|
||||
}
|
757
gui/public/i18n/it-IT.json
Normal file
757
gui/public/i18n/it-IT.json
Normal file
|
@ -0,0 +1,757 @@
|
|||
{
|
||||
"all": "Tutti",
|
||||
"none": "Nessuno",
|
||||
"never": "Mai",
|
||||
"add": "Aggiungi",
|
||||
"added": "Aggiunto",
|
||||
"activate": "Attiva",
|
||||
"summary": "Sommario",
|
||||
"approve": "Approva",
|
||||
"authenticate": "Autentica",
|
||||
"cancel": "Annulla",
|
||||
"close": "Chiudi",
|
||||
"copy": "Copia",
|
||||
"copied": "Copiato",
|
||||
"delete": "Elimina",
|
||||
"deleted": "Eliminato",
|
||||
"remove": "Rimuovi",
|
||||
"duplicate": "Duplica",
|
||||
"duplicated": "Duplicato",
|
||||
"edit": "Modifica",
|
||||
"edited": "Modificato",
|
||||
"download": "Scarica",
|
||||
"upload": "Carica",
|
||||
"uploaded": "Caricato",
|
||||
"import": "Importa",
|
||||
"export": "Esporta",
|
||||
"exported": "Esportato",
|
||||
"pdf": "PDF",
|
||||
"test": "Test",
|
||||
"configure": "Configura",
|
||||
"error": "Errore",
|
||||
"file": "File",
|
||||
"insert": "Inserisci",
|
||||
"invite": "Invita",
|
||||
"message": "Messaggio",
|
||||
"join": "Unisciti",
|
||||
"leave": "Lascia",
|
||||
"login": "Accedi",
|
||||
"logout": "Esci",
|
||||
"authentication": "Autenticazione",
|
||||
"move": "Sposta",
|
||||
"moved": "Spostato",
|
||||
"next": "Avanti",
|
||||
"ok": "OK",
|
||||
"preview": "Anteprima",
|
||||
"preview_wait": "Generazione anteprima in corso...",
|
||||
"pdf_prepare": "Preparazione PDF...",
|
||||
"publish": "Pubblica",
|
||||
"print": "Stampa",
|
||||
"reject": "Rifiuta",
|
||||
"rejected": "Rifiutato",
|
||||
"reply": "Rispondi",
|
||||
"replied": "Risposto",
|
||||
"reset": "Reimposta",
|
||||
"request": "Richiesta",
|
||||
"requested": "Richiesto",
|
||||
"save": "Salva",
|
||||
"saved": "Salvato",
|
||||
"search": "Cerca",
|
||||
"send": "Invia",
|
||||
"share": "Condividi",
|
||||
"discard": "Scarta",
|
||||
"continue": "Continua",
|
||||
"code": "Codice",
|
||||
"signin": "Accedi",
|
||||
"sort": "Ordina",
|
||||
"sort_ascending": "Crescente",
|
||||
"sort_descending": "Decrescente",
|
||||
"sort_by_name": "Nome",
|
||||
"sort_by_created": "Data di creazione",
|
||||
"sort_by_revised": "Ultimo aggiornamento",
|
||||
"unassigned": "Non assegnato",
|
||||
"update": "Aggiorna",
|
||||
"updating": "Aggiornamento in corso",
|
||||
"viewed": "Visto",
|
||||
"name": "Nome",
|
||||
"description": "Descrizione",
|
||||
"excerpt": "Estratto",
|
||||
"icon": "Icona",
|
||||
"color": "Colore",
|
||||
"visibility": "Visibilità",
|
||||
"running": "In esecuzione...",
|
||||
"firstname": "Nome",
|
||||
"lastname": "Cognome",
|
||||
"email": "Email",
|
||||
"email_recipient": "Email del destinatario",
|
||||
"password": "Password",
|
||||
"password_new": "Nuova password",
|
||||
"username": "Nome utente",
|
||||
"user": "Utente",
|
||||
"password_confirm": "Conferma password",
|
||||
"encryption": "Crittografia",
|
||||
"notice": "Avviso",
|
||||
"backup": "Backup",
|
||||
"restore": "Ripristina",
|
||||
"completed": "Completato",
|
||||
"please_wait": "Attendere...",
|
||||
"filter": "Filtro",
|
||||
"not_found": "Non trovato",
|
||||
"nothing_found": "Nessun risultato trovato",
|
||||
"expand_collapse": "Espandi/comprimi",
|
||||
"options": "Opzioni",
|
||||
"settings": "Impostazioni",
|
||||
"about": "Informazioni",
|
||||
"meta": "Metadati",
|
||||
"permissions": "Permessi",
|
||||
"profile": "Profilo",
|
||||
"go_top": "Torna all'inizio",
|
||||
"help": "Aiuto",
|
||||
"reference": "riferimento",
|
||||
"references": "riferimenti",
|
||||
"move_up": "Sposta su",
|
||||
"move_down": "Sposta giù",
|
||||
"indent": "Aumenta rientro",
|
||||
"outdent": "Riduci rientro",
|
||||
"default": "Predefinito",
|
||||
"no_undo": "Procedi con cautela poiché non è possibile annullare",
|
||||
"show_hide": "Mostra/nascondi",
|
||||
"sent": "Inviato",
|
||||
"everyone": "tutti",
|
||||
"ip": "IP",
|
||||
"event": "Evento",
|
||||
"when": "Quando",
|
||||
"last_seen": "Ultima visualizzazione",
|
||||
"change": "Cambia",
|
||||
"no_access": "Accesso negato",
|
||||
"drag_drop_reorder": "Trascina e rilascia per riordinare",
|
||||
"select": "Seleziona",
|
||||
"locale": "Locale",
|
||||
|
||||
"public": "Pubblico",
|
||||
"public_explain": "Pubblico - visibile a tutti",
|
||||
"protected": "Protetto",
|
||||
"protected_explain": "Protetto - accesso limitato agli utenti selezionati",
|
||||
"personal": "Personale",
|
||||
"personal_explain": "Personale - visibile solo da me",
|
||||
"label": "Etichetta",
|
||||
"labels": "Etichette",
|
||||
"labels_none": "Nessuna etichetta",
|
||||
"label_unclassified": "Non classificato",
|
||||
"draft": "Bozza",
|
||||
"drafted": "Bozzato",
|
||||
"draft_explain": "Bozza - deve essere approvato prima della pubblicazione, nessuna cronologia delle revisioni",
|
||||
"drafts": "Bozze",
|
||||
"live": "Pubblicato",
|
||||
"live_explain": "Pubblicato - pubblicato alla creazione",
|
||||
"archived": "Archiviato",
|
||||
"archived_explain": "Archiviato - non visibile a nessuno",
|
||||
"approved": "Approvato",
|
||||
"reverted": "Ripristinato",
|
||||
"published": "Pubblicato",
|
||||
"space": "Spazio",
|
||||
"spaces": "Spazi",
|
||||
"category": "Categoria",
|
||||
"category_explain": "Assegna categorie ai documenti e decidi chi può vederli",
|
||||
"categories": "Categorie",
|
||||
"tag": "Tag",
|
||||
"tags": "Tag",
|
||||
"tag_rules": "Specifica fino a {1} tag: solo minuscole, caratteri, numeri, trattini",
|
||||
"revisions": "Revisioni",
|
||||
"versions": "Versioni",
|
||||
"version": "Versione",
|
||||
"versioned": "Versionato",
|
||||
"versions_explain": "Crea più versioni dello stesso contenuto: gli utenti possono selezionare quale versione visualizzare",
|
||||
"change_control": "Controllo delle modifiche",
|
||||
"change_control_explain": "Seleziona il metodo di controllo delle modifiche",
|
||||
"pin": "Punta",
|
||||
"pinned": "Puntato",
|
||||
"unpin": "Sblocca",
|
||||
"unpinned": "Sbloccato",
|
||||
"blocks": "Blocchi di contenuto",
|
||||
"blocks_explain": "I blocchi di contenuto forniscono contenuti riutilizzabili che possono essere inseriti in qualsiasi documento",
|
||||
"block_delete_confirm": "Sei sicuro di voler eliminare questo blocco di contenuto riutilizzabile?",
|
||||
"actions": "Azioni",
|
||||
"activity": "Attività",
|
||||
"activity_explain": "Segnalazione dell'attività dell'utente, inclusi aggiunte, visualizzazioni, aggiornamenti, approvazioni",
|
||||
"reports": "Report",
|
||||
"content": "Contenuto",
|
||||
"template": "Modello",
|
||||
"templates": "Modelli",
|
||||
"document": "Documento",
|
||||
"documents": "Documenti",
|
||||
"attachments": "Allegati",
|
||||
"history": "Cronologia",
|
||||
"bookmark": "Segnalibro",
|
||||
"bookmarks": "Segnalibri",
|
||||
"bookmark_remove": "Rimuovi segnalibro",
|
||||
"new": "Nuovo",
|
||||
"copy_link": "Copia link",
|
||||
"created": "Creato",
|
||||
"markdown": "Markdown accettato",
|
||||
"rename": "Rinomina",
|
||||
"status": "Stato",
|
||||
"expiry": "Scadenza",
|
||||
"feedback": "Feedback",
|
||||
"un_categorized": "Non categorizzato",
|
||||
|
||||
"toc": "indice",
|
||||
"new_canvas": "Tela vuota",
|
||||
"new_template": "Da modello",
|
||||
"new_import": "Importa file",
|
||||
"new_import_explain1": "Clicca per selezionare i file o trascina i file qui",
|
||||
"new_import_explain2": ".doc, .docx, .md, .markdown",
|
||||
"new_content": "Nuovo Contenuto",
|
||||
"export_html": "Esporta come HTML",
|
||||
"export_html_explain1": "Esporta tutto il contenuto dello spazio come HTML o seleziona categorie.",
|
||||
"export_html_explain2": "Tutto il contenuto dello spazio verrà esportato come un singolo file HTML autocontenuto.",
|
||||
"import_convert": "Conversione di {1}",
|
||||
"import_success": "{1} convertito con successo",
|
||||
"add_recent": "Aggiunto di recente",
|
||||
"update_recent": "Aggiornato di recente",
|
||||
"space_change": "Sposta in un altro spazio",
|
||||
"space_change_prompt": "Seleziona lo spazio",
|
||||
"space_new": "Nuovo Spazio",
|
||||
"space_name": "Nome spazio",
|
||||
"space_name_rules": "Solo caratteri e numeri",
|
||||
"space_description": "Descrizione spazio",
|
||||
"space_clone": "Clona Spazio",
|
||||
"space_select": "Seleziona Spazio",
|
||||
"space_delete": "Elimina spazio",
|
||||
"space_delete_prompt": "Inserisci il nome dello spazio per confermare",
|
||||
"space_delete_warn": "Questo eliminerà tutti i documenti e i modelli all'interno di questo spazio!",
|
||||
"space_copy": "Copia modelli, permessi, documenti da spazio esistente",
|
||||
"space_copy_template": "Copia modelli",
|
||||
"space_copy_permission": "Copia permessi",
|
||||
"space_copy_document": "Copia documenti",
|
||||
"space_empty_state": "Aggiungi documenti tramite + CONTENUTO",
|
||||
"space_lockout": "I permessi dello spazio ti impediscono di visualizzare e creare documenti",
|
||||
"space_invite_message": "Ciao, sto condividendo lo spazio {1} (in {2}) con te per collaborare alla documentazione.",
|
||||
"protection_none": "Modifiche consentite senza approvazione",
|
||||
"protection_lock": "Bloccato, modifiche non consentite",
|
||||
"protection_review": "Le modifiche richiedono l'approvazione prima della pubblicazione",
|
||||
"template_published": "Modello pubblicato",
|
||||
"block_explain": "I blocchi di contenuto forniscono contenuti riutilizzabili che possono essere inseriti in qualsiasi documento",
|
||||
"block_published": "Blocco pubblicato",
|
||||
"upload_attachment": "Carica allegati",
|
||||
"content_revisions": "Revisioni contenuto",
|
||||
"content_revisions_explain": "Rivedi le modifiche precedenti al contenuto e ripristina le modifiche",
|
||||
"move_documents": "Sposta documenti",
|
||||
"delete_documents": "Elimina documenti",
|
||||
"feedback_enable": "Abilita feedback",
|
||||
"feedback_prompt": "Prompt di feedback",
|
||||
"feedback_prompt_hint": "Inserisci il prompt per chiedere il feedback dell'utente",
|
||||
"feedback_prompt_explain": "Specifica il prompt, ad esempio 'Ti è stato utile? È stato utile? Hai trovato quello che cercavi?'",
|
||||
"feedback_thanks": "Grazie per il feedback!",
|
||||
"feedback_help_yes": "Sì, grazie!",
|
||||
"feedback_help_no": "Non proprio",
|
||||
"likes_prompt": "Ti è stato utile?",
|
||||
"delete_confirm": "Sei sicuro di voler eliminare?",
|
||||
"category_assignment_summary": "Assegnato a {1} documenti e visibile da {2} utenti/gruppi",
|
||||
"category_no_access": "Non hai il permesso di visualizzazione per questa categoria",
|
||||
"category_default": "Categoria predefinita per nuovo contenuto",
|
||||
"category_default_explain": "Si applica automaticamente ai documenti appena creati",
|
||||
"category_delete_confirm": "Sei sicuro di voler eliminare questa categoria?",
|
||||
"category_permissions": "Permessi categoria",
|
||||
"category_permissions_explain": "Seleziona chi può visualizzare i documenti all'interno della categoria",
|
||||
"category_none": "Questo spazio non ha ancora categorie",
|
||||
|
||||
"approval_anybody": "Approvazione richiesta da qualsiasi approvatore",
|
||||
"approval_majority": "Approvazione della maggioranza richiesta dagli approvatori",
|
||||
"approval_unanimous": "Approvazione unanime richiesta da tutti gli approvatori",
|
||||
"approval_pending": "Modifiche in sospeso",
|
||||
"approval_awaiting": "In attesa di approvazione",
|
||||
"protection_type_open": "Aperto",
|
||||
"protection_type_protected": "Protetto",
|
||||
"protection_type_locked": "Bloccato",
|
||||
"doc_request_contribution": "Richiesta contributo",
|
||||
"doc_request_feedback": "Richiesta feedback",
|
||||
"doc_request_read": "Richiesta lettura",
|
||||
"doc_request_publication": "Richiesta pubblicazione",
|
||||
"doc_request_approval": "Richiesta approvazione",
|
||||
"doc_withdraw_approval": "Ritira la richiesta",
|
||||
"doc_withdraw_approval_reason": "Spiegazione",
|
||||
"doc_withdraw_approval_reason_explain": "Nota utile che spiega il motivo, ad esempio correzioni, aggiunte",
|
||||
"doc_review_publish": "Per favore, puoi rivedere e approvare le modifiche?",
|
||||
"doc_review_discard": "Vorrei ritirare questa richiesta di approvazione.",
|
||||
"doc_contribution_pending": "Hai una modifica in sospeso",
|
||||
"doc_contribution_under_review": "La tua richiesta di approvazione è in fase di revisione",
|
||||
"doc_contribution_rejected": "La tua modifica è stata respinta",
|
||||
"doc_contribution_review": "Rivedi le modifiche ({1})",
|
||||
"doc_change_status": "Modifiche {1} in corso, {2} in attesa di revisione, {3} respinte",
|
||||
"doc_approve_reject": "Approva/Rifiuta le modifiche",
|
||||
"doc_approve_method": "Metodo di approvazione",
|
||||
"doc_approve_status": "Stato di approvazione",
|
||||
"doc_approver_status": "{1} approvazioni e {2} respinte con {3} approvatori coinvolti in questa revisione",
|
||||
"doc_publish": "Per favore, puoi spostare questo documento da Bozza a Pubblicato? Siamo pronti per pubblicarlo!",
|
||||
"doc_category_explain": "Assegna una o più categorie per aiutare a organizzare il contenuto all'interno di questo spazio",
|
||||
"doc_action_request_ask": "Chiedi",
|
||||
"doc_action_request_to": "A",
|
||||
"doc_action_request_by": "Da",
|
||||
"revision_none": "Nessuna revisione effettuata",
|
||||
"revision_restore": "Ripristina sezione",
|
||||
"revision_restore_confirm": "Sei sicuro di voler ripristinare questa revisione?",
|
||||
"template_save": "Salva come modello",
|
||||
"template_name_explain": "Un buon nome del modello comunica il tipo di documento",
|
||||
"template_desc_explain": "Spiega l'uso di questo modello",
|
||||
"print_explain": "Stampa tutto il contenuto o seleziona le sezioni",
|
||||
"doc_delete_confirm": "Sei sicuro di voler eliminare questo documento?",
|
||||
"attachment_delete": "Elimina allegato",
|
||||
"attachment_delete_confirm": "Sei sicuro di voler eliminare questo allegato?",
|
||||
"link_insert": "Inserisci link",
|
||||
"link_type_section": "Sezione",
|
||||
"link_type_section_explain": "Collegamento a contenuti all'interno di questo documento",
|
||||
"link_type_attachment": "Allegato",
|
||||
"link_type_attachment_explain": "Collegamento a un allegato all'interno di questo documento",
|
||||
"link_type_search": "Ricerca",
|
||||
"link_type_search_explain": "Nome del documento, contenuto, nome dell'allegato",
|
||||
"link_type_network": "Rete",
|
||||
"link_type_network_explain": "Specifica la posizione della cartella/condivisione della rete",
|
||||
"link_type_network_example": "es. //condivisione/cartella",
|
||||
"discard_changes": "Annulla le modifiche",
|
||||
"discard_confirm": "Hai apportato modifiche - continuare a modificare o annullare le modifiche?",
|
||||
"share_expire_2": "in 2 giorni",
|
||||
"share_expire_7": "in 7 giorni",
|
||||
"share_expire_14": "in 14 giorni",
|
||||
"share_expire_30": "in 30 giorni",
|
||||
"share_expire_60": "in 60 giorni",
|
||||
"share_expire_90": "in 90 giorni",
|
||||
|
||||
"actions_mine": "Azioni assegnate a te",
|
||||
"actions_none": "Non hai azioni",
|
||||
"actions_due": "scadenza",
|
||||
"actions_see_note": "leggi la nota",
|
||||
"actions_mark_complete": "segna come completato",
|
||||
"actions_completed": "completate",
|
||||
"actions_see_more": "{1} azioni completate →",
|
||||
"actions_requested": "Azioni che hai assegnato ad altri",
|
||||
"actions_requested_none": "Non hai fatto richieste",
|
||||
"actions_requested_more": "{1} richieste completate di recente →",
|
||||
"actions_requested_complete": "{1} richieste completate →",
|
||||
"activity_period": "Periodo di tempo",
|
||||
"activity_filter_past": "Passato",
|
||||
"activity_filter_days": "Giorni",
|
||||
"activity_filter_for": "Per",
|
||||
"audit_24": "24 ore",
|
||||
"audit_7": "7 giorni",
|
||||
"audit_14": "14 giorni",
|
||||
"audit_30": "30 giorni",
|
||||
"audit_90": "90 giorni",
|
||||
"chat_leave_comment": "Lascia un commento",
|
||||
"chat_applies_to": "Si applica a",
|
||||
"chat_delete_confirm": "Sei sicuro di voler eliminare questo commento?",
|
||||
"chat_reply_delete_confirm": "Sei sicuro di voler eliminare questa risposta?",
|
||||
"doc_secure_share": "Condividi tramite link esterno sicuro",
|
||||
"doc_secure_shared_by": "Condiviso da",
|
||||
"doc_version_viewed": "Rinomina versione",
|
||||
"doc_version_remove": "Annulla la versione",
|
||||
"doc_version_create": "Crea versione del documento",
|
||||
"doc_version_explain": "Le versioni vengono assegnate ai documenti in cui ogni versione è un documento diverso.",
|
||||
"doc_version_label": "Etichetta versione",
|
||||
"doc_version_label_explain": "es. 1.0, v1.0, Versione 1, Rilascio 2018.1",
|
||||
"doc_version_this": "Crea una nuova versione di questo documento",
|
||||
"doc_version_select": "o seleziona un altro documento",
|
||||
"doc_version_assign": "Assegna la versione a questo documento",
|
||||
"doc_version_dropdown": "<assegna la versione a un altro documento>",
|
||||
"doc_version_remove_confirm": "Sei sicuro di voler rimuovere questa versione e tutto il suo contenuto?",
|
||||
"doc_version_remove_name": "Conferma digitando il nome del documento qui sotto",
|
||||
"doc_version_unversion": "L'operazione di un-version renderà il documento indipendente mantenendo intatto tutto il contenuto.",
|
||||
"doc_version_unversion_confirm": "Sei sicuro di voler annullare la versione del documento?",
|
||||
"archived_content": "Contenuto archiviato",
|
||||
"archived_content_explain": "Contrassegna il contenuto archiviato come attivo",
|
||||
"unarchive_content": "Ripristina contenuto",
|
||||
|
||||
"document_permissions": "Permessi documento",
|
||||
"space_permissions": "Permessi spazio",
|
||||
"space_permissions_explain": "Assegna permessi agli utenti o ai gruppi e invita nuovi utenti a questo spazio",
|
||||
"space_permission_view": "Visualizzazione",
|
||||
"space_permission_view_explain": "Visualizza il contenuto all'interno di questo spazio",
|
||||
"space_permission_manage": "Gestione",
|
||||
"space_permission_manage_explain": "Gestisci tutti gli aspetti dello spazio tranne l'eliminazione",
|
||||
"space_permission_owner": "Proprietario",
|
||||
"space_permission_owner_explain": "Gestisci ed elimina lo spazio",
|
||||
"space_permission_doc_create": "Crea",
|
||||
"space_permission_doc_create_explain": "Può creare nuovi documenti nello spazio",
|
||||
"space_permission_doc_edit": "Modifica",
|
||||
"space_permission_doc_edit_explain": "Può modificare il contenuto del documento",
|
||||
"space_permission_doc_delete": "Elimina",
|
||||
"space_permission_doc_delete_explain": "Può rimuovere documenti dallo spazio",
|
||||
"space_permission_doc_move": "Sposta",
|
||||
"space_permission_doc_move_explain": "Può spostare documenti da questo spazio a un altro spazio",
|
||||
"space_permission_doc_copy": "Copia",
|
||||
"space_permission_doc_copy_explain": "Può duplicare i documenti",
|
||||
"space_permission_doc_template": "Modelli",
|
||||
"space_permission_doc_template_explain": "Può creare e pubblicare modelli di documenti",
|
||||
"space_permission_doc_approval": "Approvazione",
|
||||
"space_permission_doc_approval_explain": "Può (1) approvare o respingere le modifiche al documento; (2) spostare documenti da bozza a pubblicato",
|
||||
"space_permission_doc_draft": "Bozza",
|
||||
"space_permission_doc_draft_explain": "Può visualizzare e lavorare su documenti contrassegnati come bozze",
|
||||
"space_permission_doc_version": "Versioni",
|
||||
"space_permission_doc_version_explain": "Può creare versioni del documento e collegarle tra loro",
|
||||
"space_permission_add_user": "Aggiungi utenti a questo spazio",
|
||||
"space_permission_invite_user": "Invita utenti a questo spazio",
|
||||
"space_permission_invite_explain": "Separa con la virgola più indirizzi email",
|
||||
"section_insert": "Inserisci Sezione",
|
||||
"section_insert_here": "Inserisci sezione qui",
|
||||
"section_copy_explain": "Questa sezione e tutte le sezioni nidificate verranno copiate nel documento selezionato.",
|
||||
"section_move_explain": "Questa sezione e tutte le sezioni nidificate verranno spostate nel documento selezionato.",
|
||||
"section_delete": "Sei sicuro di voler eliminare questa sezione?",
|
||||
"section_delete_children": "Elimina anche le sezioni figlie",
|
||||
"section_publish": "Pubblica Blocco di Contenuto Riutilizzabile",
|
||||
"section_publish_name_explain": "Fornisci un titolo breve per il blocco di contenuto riutilizzabile",
|
||||
"section_publish_desc_explain": "Breve descrizione per aiutare gli altri a capire il blocco di contenuto riutilizzabile",
|
||||
"section_airtable": "Airtable",
|
||||
"section_airtable_explain": "Parte foglio di calcolo, parte database e completamente flessibile (https://airtable.com)",
|
||||
"section_airtable_code": "Codice di incorporamento di Airtable",
|
||||
"section_code_tip": "Nome conciso che descrive lo snippet di codice",
|
||||
"section_drawio": "Diagrams.net",
|
||||
"section_drawio_explain": "Per creare diagrammi di flusso, diagrammi di processo, organigrammi, diagrammi UML, diagrammi ER, diagrammi di rete e molto altro ancora (https://www.diagrams.net)",
|
||||
"section_iframe": "iFrame",
|
||||
"section_iframe_explain": "Incorpora un iFrame",
|
||||
"section_iframe_code": "Codice di incorporamento di iFrame",
|
||||
"section_gemini": "Gemini",
|
||||
"section_gemini_explain": "Software di monitoraggio delle issue e help desk aziendale Gemini (https://www.countersoft.com)",
|
||||
"section_gemini_url": "URL di Gemini",
|
||||
"section_gemini_url_explain": "ad es. https://helpdesk.countersoft.com",
|
||||
"section_gemini_key": "Chiave API (dal profilo utente)",
|
||||
"section_gemini_workspace": "Spazio di lavoro",
|
||||
"section_jira": "Jira Software",
|
||||
"section_jira_explain": "Jira fornisce il tracciamento delle issue e il software agile",
|
||||
"section_jira_admin": "L'amministratore della tua Community Documize deve fornire i dettagli di connessione Jira prima dell'uso.",
|
||||
"section_jira_no_auth": "Connettore Jira non autenticato",
|
||||
"section_papertrail": "Papertrail",
|
||||
"section_papertrail_explain": "Visualizza i log basati su cloud (https://papertrailapp.com)",
|
||||
"section_papertrail_key": "Chiave API di Papertrail",
|
||||
"section_papertrail_search": "Query di ricerca",
|
||||
"section_papertrail_search_explain": "Determina quali voci di log vuoi visualizzare, ad es. bob OPPURE (\"alcune frasi\" E sally)",
|
||||
"section_papertrail_max": "Risultati massimi",
|
||||
"section_papertrail_max_explain": "Quante voci di log desideri?",
|
||||
"section_papertrail_group": "Gruppo",
|
||||
"section_papertrail_group_explain": "Gruppo Papertrail opzionale",
|
||||
"section_pdf": "Visualizzatore PDF",
|
||||
"section_pdf_upload_explain": "Il primo PDF caricato verrà utilizzato",
|
||||
"section_pdf_height": "Altezza anteprima",
|
||||
"section_pdf_height_explain": "Quanto alta è l'anteprima PDF?",
|
||||
"section_pdf_start": "Pagina di inizio",
|
||||
"section_pdf_start_explain": "La prima pagina da visualizzare",
|
||||
"section_pdf_sidebar": "Barra laterale",
|
||||
"section_pdf_sidebar_explain": "Opzionalmente, imposta il contenuto della barra laterale",
|
||||
"section_pdf_sidebar_none": "Nessuna",
|
||||
"section_pdf_sidebar_bookmark": "Segnalibri",
|
||||
"section_pdf_sidebar_thumbnail": "Miniature",
|
||||
"section_plantuml": "PlantUML",
|
||||
"section_plantuml_explain": "Crea diagrammi UML da un linguaggio di testo semplice (http://plantuml.com)",
|
||||
"section_plantuml_link": "Diagramma PlantUML",
|
||||
"section_plantuml_type_sequence": "Sequenza",
|
||||
"section_plantuml_type_usecase": "Caso d'uso",
|
||||
"section_plantuml_type_class": "Classe",
|
||||
"section_plantuml_type_activity": "Attività",
|
||||
"section_plantuml_type_activity2": "Attività (nuova sintassi)",
|
||||
"section_plantuml_type_component": "Componente",
|
||||
"section_plantuml_type_state": "Stato",
|
||||
"section_tabular_import_csv": "Importa CSV",
|
||||
"section_tabular_csv": "CSV in Tabella",
|
||||
"section_tabular_warn": "Nota: i dati della tabella esistente saranno sostituiti",
|
||||
"section_tabular_paste": "Incolla Dati CSV",
|
||||
"section_tabular_format": "Sono supportati i delimitatori comuni",
|
||||
"section_tabular_first_row": "Intestazione della prima riga",
|
||||
"section_tabular_first_row_explain": "Abilita se la prima riga contiene le intestazioni",
|
||||
"section_trello": "Trello",
|
||||
"section_trello_explain": "Trello è il modo visivo per gestire i tuoi progetti e organizzare qualsiasi cosa (https://trello.com)",
|
||||
"section_trello_none": "Non hai bacheche del team da condividere: le bacheche personali non vengono mai mostrate",
|
||||
"section_trello_admin": "L'amministratore della tua Community Documize deve configurare Trello prima dell'uso.",
|
||||
"section_trello_board": "Bacheca",
|
||||
"section_trello_list": "Lista",
|
||||
|
||||
"login_cas": "Autenticazione con CAS...",
|
||||
"login_cass_error": "Fallimento dell'autenticazione CAS",
|
||||
"login_keycloak": "Autenticazione con Keycloak...",
|
||||
"login_keycloak_error": "Fallimento dell'autenticazione Keycloak",
|
||||
"login_invalid": "Credenziali non valide",
|
||||
"forgot_password": "Hai dimenticato la password?",
|
||||
"reset_password": "Ripristina la password",
|
||||
"reset_password_next": "Grazie. Controlla la tua email per le istruzioni.",
|
||||
"password_strong": "Scegli una password sicura",
|
||||
"password_match": "Le password devono corrispondere",
|
||||
"welcome": "Benvenuto in Documize",
|
||||
"welcome_explain": "Impostiamo il tuo account e iniziamo",
|
||||
"profile_explain": "Gestisci il tuo profilo e la tua password",
|
||||
"search_hint": "parole chiave, tag",
|
||||
"search_too_short": "La tua query di ricerca è troppo breve",
|
||||
"search_doc_name": "Nome del documento",
|
||||
"search_doc_content": "Contenuto del documento",
|
||||
"search_tag_name": "Nome del tag",
|
||||
"search_attachment_name": "Nome dell'allegato",
|
||||
"search_example_title": "Esempi di query",
|
||||
"search_explain": "Trova contenuti utilizzando parole chiave e operatori",
|
||||
"search_example1": "Mostra risultati che contengono almeno una delle due parole",
|
||||
"search_example2": "Mostra risultati che contengono entrambe le parole",
|
||||
"search_example3": "Mostra risultati che contengono la parola \"mela\", ma posiziona le righe più in alto se contengono anche \"macintosh\"",
|
||||
"search_example4": "Mostra risultati che contengono la parola \"mela\" ma non \"macintosh\"",
|
||||
"search_example5": "Mostra risultati che contengono le parole \"mela\" e \"turnover\" o \"mela\" e \"strudel\" (in qualsiasi ordine), ma posiziona \"mela turnover\" più in alto di \"mela strudel\"",
|
||||
"search_example6": "Mostra risultati che contengono parole come \"mela\", \"mele\", \"composta di mele\" o \"applet\"",
|
||||
"search_example7": "Mostra risultati che contengono l'esatta frase \"alcune parole\" (ad esempio, righe che contengono \"alcune parole di saggezza\" ma non \"alcune parole di rumore\")",
|
||||
"search_example8": "Mostra risultati che contengono una delle due parole",
|
||||
"search_example9": "Mostra risultati che hanno \"google\", sia \"mela\" che \"microsoft\" ma non \"ibm\"",
|
||||
"search_example10": "Mostra risultati che contengono parole che iniziano con \"mela\", come \"composta di mele\" o \"applet\"",
|
||||
"space_density_complete": "Completa",
|
||||
"space_density_comfort": "Comfort",
|
||||
"space_density_compact": "Compatto",
|
||||
|
||||
"backup_explain1": "Documize Community è un'applicazione multi-tenant che consente a entrambi 'tech.mycompany.com' e 'sales.mycompany.com' di funzionare utilizzando lo stesso eseguibile/database. In qualità di Amministratore Globale della Community Documize, effettuerai un backup completo di sistema in tutti i tenant. L'Amministratore Tenant della Community Documize può effettuare un backup a livello di tenant (ad esempio, marketing.mycompany.com).",
|
||||
"backup_explain2": "Documize Community è un'applicazione multi-tenant che consente a entrambi 'tech.mycompany.com' e 'sales.mycompany.com' di funzionare utilizzando lo stesso eseguibile/database. In qualità di Amministratore Globale della Community Documize, effettuerai un backup completo di sistema in tutti i tenant. In qualità di Amministratore Tenant della Community Documize, puoi effettuare un backup a livello di tenant (ad esempio, marketing.mycompany.com).",
|
||||
"backup_explain3": "Il processo di backup può richiedere diversi minuti -- per favore, sii paziente durante l'operazione di backup.",
|
||||
"backup_retain": "Mantieni il file di backup sul server",
|
||||
"backup_running": "Backup in corso, per favore attendi...",
|
||||
"backup_tenant": "Backup del Tenant",
|
||||
"backup_system": "Backup di Sistema",
|
||||
"backup_failed": "Backup non riuscito -- per favore verifica i log del server",
|
||||
"backup_success": "Backup riuscito",
|
||||
"backup_start": "Avvia Backup",
|
||||
"backup_run": "Esegui Backup",
|
||||
"restore_explain1": "Il ripristino da un backup di sistema dovrebbe essere effettuato solo su un database Documize Community vuoto.",
|
||||
"restore_explain2": "L'operazione di ripristino ricreerà utenti, gruppi, autorizzazioni, spazi, categorie e contenuti.",
|
||||
"restore_explain3": "Il processo di ripristino può richiedere diversi minuti -- per favore, sii paziente durante l'operazione di ripristino.",
|
||||
"restore_select_file": "Scegli il file di backup",
|
||||
"restore_running": "Per favore attendi, ripristino in corso...",
|
||||
"restore_failed": "Ripristino non riuscito -- per favore verifica i log del server",
|
||||
"restore_success": "Ripristino completato -- riavvia il tuo browser e accedi",
|
||||
"restore_confirm": "Conferma Ripristino",
|
||||
"restore_confirm_input": "Per avviare il processo, digita RIPRISTINA",
|
||||
"restore_warn": "Dovresti effettuare il ripristino solo su un'istanza Documize Community vuota",
|
||||
"changelog_available": "È disponibile un aggiornamento del prodotto",
|
||||
"changelog_guidance": "Per l'aggiornamento, sostituisci l'eseguibile esistente e riavvia Documize Community.",
|
||||
"customize_name": "Nome del Sito",
|
||||
"customize_name_explain": "Fornisci un titolo breve per questa istanza di Documize Community",
|
||||
"customize_message": "Messaggio del Sito",
|
||||
"customize_message_explain": "Fornisci un breve messaggio che spiega questa istanza di Documize Community",
|
||||
"customize_theme": "Tema del Sito",
|
||||
"customize_logo": "Logo del Sito",
|
||||
"customize_logo_default": "Usa Predefinito",
|
||||
"customize_logo_upload": "Carica Personalizzato",
|
||||
"customize_logo_explain": "Puoi scegliere di caricare un logo piccolo (ad esempio, 64px x 64px)",
|
||||
"customize_subdomain": "Sottodominio URL del Sito",
|
||||
"customize_subdomain_explain": "Se stai ospitando su 'docs.example.org', il valore del sottodominio dovrebbe essere impostato su 'docs'",
|
||||
"customize_anon": "Spazi Pubblici Visibili dagli Utenti Anonimi",
|
||||
"customize_anon_explain": "Condividi contenuti con visitatori del sito non autenticati",
|
||||
"customize_conversion_url": "URL del Servizio di Conversione",
|
||||
"customize_conversion_explain": "Endpoint per la gestione di importazione/esportazione",
|
||||
"customize_tags": "Massimo di Tag per Documento",
|
||||
"customize_tags_explain": "Quanti tag possono essere assegnati a un documento (tra 3 e 10 tag)",
|
||||
"integration_jira_url": "URL",
|
||||
"integration_jira_url_explain": "Nome di dominio completamente qualificato per la tua istanza Jira, ad esempio http://jira.example.org",
|
||||
"integration_jira_username": "Nome Utente",
|
||||
"integration_jira_username_explain": "Il tuo nome utente/email di accesso a Jira",
|
||||
"integration_jira_password": "Password",
|
||||
"integration_jira_password_explain": "Fornisci il Token API se utilizzi Atlassian Cloud o la Password se stai auto-ospitando Jira",
|
||||
"integration_trello_appkey": "Chiave App",
|
||||
"search_reindex": "La ricostruzione dell'indice di ricerca può richiedere fino a 30 minuti.",
|
||||
"search_reindex_rebuild": "Ricostruisci",
|
||||
"search_reindex_start": "Avvio del processo di ricostruzione dell'indice di ricerca",
|
||||
"search_reindex_finish": "Ricostruzione dell'indice di ricerca completata",
|
||||
"smtp_host": "Host",
|
||||
"smtp_host_explain": "ad esempio, mio.host.com",
|
||||
"smtp_port": "Porta",
|
||||
"smtp_port_explain": "ad esempio, 587",
|
||||
"smtp_username": "Nome Utente",
|
||||
"smtp_username_explain": "ad esempio, nome utente di accesso al server SMTP",
|
||||
"smtp_password": "Password",
|
||||
"smtp_password_explain": "ad esempio, password di accesso al server SMTP",
|
||||
"smtp_sender_email": "Email del Mittente",
|
||||
"smtp_sender_email_explain": "ad esempio, user@example.org",
|
||||
"smtp_sender_name": "Nome del Mittente",
|
||||
"smtp_sender_name_explain": "ad esempio, Documize",
|
||||
"smtp_fqdn": "Nome di Dominio Completo del Server del Mittente",
|
||||
"smtp_fqdn_explain": "(opzionale) SMTP può richiedere un nome di dominio valido, ad esempio docs.example.org",
|
||||
"smtp_anon_auth": "Autenticazione Anonima (Ignora le Credenziali)",
|
||||
"smtp_base64": "Codifica in Base64 delle Credenziali",
|
||||
"smtp_ssl": "Usa SSL",
|
||||
"smtp_save_test": "Salva e Testa",
|
||||
"smtp_sent_test_email": "Invio di una email di test a te",
|
||||
"smtp_missing": "Impostazioni del server di posta mancanti",
|
||||
"space_admin_export": "Esporta Tutto il Contenuto",
|
||||
"space_admin_export_running": "Esportazione in corso...",
|
||||
"space_admin_make_owner": "Aggiungimi come proprietario",
|
||||
"space_admin_empty": "Non ci sono spazi condivisi da gestire",
|
||||
"space_admin_delete_title": "Eliminazione Spazio",
|
||||
"space_admin_delete_check": "Sei sicuro di voler eliminare questo spazio e tutti i documenti?",
|
||||
"space_admin_confirm": "Digita il nome dello spazio per confermare",
|
||||
"space_admin_confirm_explain": "Ciò eliminerà tutti i documenti e i modelli all'interno di questo spazio!",
|
||||
"label_add": "Aggiungi Etichetta",
|
||||
"label_update": "Aggiorna Etichetta",
|
||||
"label_delete": "Elimina Etichetta",
|
||||
"label_delete_confirm": "Sei sicuro di voler eliminare l'etichetta {1}?",
|
||||
"user_admin_add": "Aggiungi Utenti",
|
||||
"user_admin_bulk": "Caricamento in Blocco",
|
||||
"user_admin_bulk_format": "Elenco separato da virgole: nome, cognome, email",
|
||||
"group_add": "Aggiungi Gruppo",
|
||||
"group_name_explain": "Inserisci il nome del gruppo, ad esempio, Manager, Sviluppatori, Team Acme",
|
||||
"group_member_add": "Aggiungi membro",
|
||||
"group_member_remove": "Rimuovi membro",
|
||||
"group_delete": "Elimina Gruppo",
|
||||
"group_delete_confirm": "Sei sicuro di voler eliminare questo gruppo?",
|
||||
"group_delete_name": "Per favore, digita il nome del gruppo per confermare",
|
||||
"group_delete_name_explain": "Ciò rimuoverà le informazioni di appartenenza al gruppo e le autorizzazioni associate",
|
||||
"group_none": "Nessun gruppo",
|
||||
"group_edit": "Modifica Gruppo",
|
||||
"find_user": "Trova utenti",
|
||||
"find_user_syntax": "Ricerca per nome, cognome, email",
|
||||
"user_max_display": "Massimo utenti da visualizzare",
|
||||
"user_assign_group": "Assegna gruppi agli utenti",
|
||||
"user_delete_confirm": "Sei sicuro di voler eliminare l'utente {1}?",
|
||||
"user_selected_delete_confirm": "Sei sicuro di voler eliminare gli utenti selezionati?",
|
||||
"user_delete": "Elimina Utente",
|
||||
"permission_spaces": "Spazi",
|
||||
"permission_spaces_explain": "Può aggiungere spazi, sia personali che condivisi con altri",
|
||||
"permission_visible": "Visibile",
|
||||
"permission_visible_explain": "Può vedere nomi di utenti e gruppi, può disabilitare per utenti esterni come clienti/partner",
|
||||
"permission_admin": "Amministratore",
|
||||
"permission_admin_explain": "Può gestire tutti gli aspetti di Documize Community, come questa schermata",
|
||||
"permission_analytics": "Analisi",
|
||||
"permission_analytics_explain": "Può visualizzare rapporti analitici",
|
||||
"permission_active": "Attivo",
|
||||
"permission_active_explain": "Può accedere e utilizzare Documize Community",
|
||||
"auth_role_space": "Può Creare Spazi",
|
||||
"auth_disable_logout": "Disabilita Logout",
|
||||
"auth_dual_login": "Accesso Duplice",
|
||||
"auth_dual_login_explain": "Abilita l'accesso tramite LDAP e l'email/password regolare (utile per testare LDAP)",
|
||||
"auth_email_password": "Email/Password incorporata",
|
||||
"auth_connect_keycloak": "Collegati al server di autenticazione",
|
||||
"auth_connect_ldap": "Collegati a LDAP/Active Directory",
|
||||
"auth_connect_cas": "Collegati al Central Authentication Server",
|
||||
"auth_keycloak_running": "Sincronizzazione utenti Keycloak in corso...",
|
||||
"auth_keycloak_sync": "Sincronizza con Keycloak",
|
||||
"auth_ldap_running": "Sincronizzazione utenti LDAP in corso...",
|
||||
"auth_ldap_sync": "Sincronizza con LDAP",
|
||||
"auth_keycloak_url": "URL Server Keycloak",
|
||||
"auth_keycloak_realm": "Dominio Keycloak",
|
||||
"auth_keycloak_pk": "Chiave Pubblica del Dominio Keycloak",
|
||||
"auth_keycloak_pk_explain": "Copia la Chiave Pubblica RSA dalle Impostazioni del Dominio > Chiavi",
|
||||
"auth_keycloak_oidc": "ID Client Keycloak OIDC",
|
||||
"auth_keycloak_group": "ID Gruppo Keycloak (Opzionale)",
|
||||
"auth_keycloak_group_explain": "Se vuoi sincronizzare gli utenti in un determinato Gruppo (ad esempio, 'Utenti Documize Community'), fornisci l'ID Gruppo (ad esempio, 511d8b61-1ec8-45f6-bc8d-5de64d54c9d2)",
|
||||
"auth_keycloak_username": "Nome Utente Keycloak",
|
||||
"auth_keycloak_username_explain": "Usato per collegarsi a Keycloak e sincronizzare gli utenti con Documize Community (crea l'utente sotto il Dominio Master e assegna il ruolo 'view-users' al Dominio specificato sopra)",
|
||||
"auth_keycloak_password": "Password Keycloak",
|
||||
"auth_keycloak_password_explain": "Usata per collegarsi a Keycloak e sincronizzare gli utenti con Documize Community",
|
||||
"auth_ldap_server": "Server LDAP",
|
||||
"auth_ldap_server_explain": "Indirizzo IP o host, ad esempio, ldap.example.org, 127.0.0.1",
|
||||
"auth_ldap_port": "Porta Server LDAP",
|
||||
"auth_ldap_port_explain": "Numero di porta, ad esempio, 389",
|
||||
"auth_ldap_base": "Base DN",
|
||||
"auth_ldap_base_explain": "Punto di partenza per i filtri di ricerca, ad esempio, ou=users,dc=example,dc=com",
|
||||
"auth_ldap_bind": "Bind DN",
|
||||
"auth_ldap_bind_explain": "Credenziali di accesso per il server LDAP",
|
||||
"auth_ldap_password": "Password Bind",
|
||||
"auth_ldap_filter_user": "Filtro Utente",
|
||||
"auth_ldap_filter_user_explain1": "Filtro di ricerca per trovare gli utenti, ad esempio, (|(objectClass=person)(objectClass=user)(objectClass=inetOrgPerson))",
|
||||
"auth_ldap_filter_user_explain2": "Specifica il Filtro Utente e/o il Filtro Gruppo",
|
||||
"auth_ldap_filter_group": "Filtro Gruppo",
|
||||
"auth_ldap_filter_group_explain": "Filtro di ricerca per trovare gli utenti tramite i gruppi, ad esempio, (&(objectClass=group)(|(cn=ship_crew)(cn=admin_staff)))",
|
||||
"auth_ldap_rdn": "Attributo RDN Utente",
|
||||
"auth_ldap_rdn_explain1": "Attributo nome utente/login, ad esempio, uid in LDAP, sAMAccountName in Active Directory",
|
||||
"auth_ldap_rdn_explain2": "Attributi utente utilizzati per recuperare i dati quando si utilizza il Filtro Utente",
|
||||
"auth_ldap_firstname": "Attributo Nome Utente",
|
||||
"auth_ldap_firstname_explain": "Attributo nome, ad esempio, givenName",
|
||||
"auth_ldap_lastname": "Attributo Cognome Utente",
|
||||
"auth_ldap_lastname_explain": "Attributo cognome, ad esempio, sn",
|
||||
"auth_ldap_email": "Attributo Email Utente",
|
||||
"auth_ldap_email_explain": "Attributo email, ad esempio, mail",
|
||||
"auth_ldap_group": "Attributo Membro Gruppo",
|
||||
"auth_ldap_group_explain1": "Attributo che identifica il singolo membro del gruppo, ad esempio, member o uniqueMember",
|
||||
"auth_ldap_group_explain2": "Attributi gruppo utilizzati per recuperare i dati quando si utilizza il Filtro Gruppo",
|
||||
"auth_ldap_preview": "Anteprima LDAP",
|
||||
"auth_ldap_preview_result": "Connessione riuscita, trovati {1} utenti.",
|
||||
"auth_ldap_preview_error": "Impossibile connettersi",
|
||||
"auth_cas_url": "URL Server CAS",
|
||||
"auth_cas_url_explain": "ad esempio, http://localhost:8888/auth",
|
||||
"auth_cas_back_url": "URL Documize CAS",
|
||||
"auth_cas_back_url_explain": "ad esempio, http://URL-Documize/auth/cas",
|
||||
"administration": "Amministrazione",
|
||||
"admin_general": "Generale",
|
||||
"admin_general_explain": "Opzioni per personalizzare Documize Community",
|
||||
"admin_user_management": "Gestione Utenti",
|
||||
"admin_user_management_explain": "Gestisci informazioni di base, password e autorizzazioni",
|
||||
"admin_user_groups": "Gruppi Utenti",
|
||||
"admin_user_groups_explain": "Definisci gruppi per una gestione più facile degli utenti e delle autorizzazioni",
|
||||
"admin_integrations": "Integrazioni",
|
||||
"admin_integrations_explain": "Abilita e configura integrazioni di terze parti",
|
||||
"admin_mail_server": "Server di Posta",
|
||||
"admin_mail_server_explain": "Specifica i dettagli del server di posta richiesti per l'invio di inviti agli utenti e delle email di notifica",
|
||||
"admin_audit_log": "Registro delle Attività",
|
||||
"admin_backup": "Backup e Ripristino",
|
||||
"admin_backup_explain": "Esporta tutto il contenuto in un singolo file zip autosufficiente",
|
||||
"admin_billing": "Fatturazione",
|
||||
"admin_changelog": "Registro delle Modifiche",
|
||||
"admin_auth_explain": "Scegli il provider di autenticazione degli utenti: Documize, Redhat Keycloak, LDAP/AD, Central Authentication Server",
|
||||
"admin_spaces_explain": "Elimina spazi, prendi possesso di spazi condivisi e spazi orfani",
|
||||
"admin_labels_explain": "Raggruppa e naviga tra gli spazi con etichette visive",
|
||||
"admin_search_explain": "Ricostruisci l'indice di ricerca",
|
||||
"setup_default_message": "L'istanza di Documize Community contiene tutta la nostra documentazione",
|
||||
"get_in_touch": "Contattaci",
|
||||
"product_feedback": "Hai un'idea per il prodotto, un suggerimento o un feedback?",
|
||||
"product_news": "Novità sul Prodotto",
|
||||
"product_news_explain": "Ultime novità e aggiornamenti sul prodotto",
|
||||
"product_update": "Aggiornamento disponibile",
|
||||
"product_whats_new": "Cosa c'è di nuovo",
|
||||
"product_activation_key_missing": "Chiave di attivazione mancante",
|
||||
"account_update": "Aggiorna Account",
|
||||
"404": "Ops! Questa pagina non è stata trovata.",
|
||||
"404_explain": "Forse il contenuto che stai cercando non è più disponibile?",
|
||||
"close_account": "Per favore, chiudi il mio account Documize.",
|
||||
"third_party": "Documize Community utilizza librerie e componenti open source di terze parti",
|
||||
"server_ldap_error1": "Errore: impossibile sincronizzare gli utenti con LDAP in quanto non è l'opzione configurata",
|
||||
"server_ldap_error2": "Errore: impossibile leggere i dati di configurazione LDAP",
|
||||
"server_ldap_error3": "Errore: impossibile recuperare gli utenti LDAP: {1}",
|
||||
"server_ldap_complete": "Sincronizzazione completata con il server LDAP",
|
||||
"server_ldap_summary": "La sincronizzazione LDAP ha trovato {1} utenti, {2} nuovi utenti aggiunti, {3} utenti con dati mancanti ignorati",
|
||||
"server_keycloak_error1": "Errore: impossibile sincronizzare gli utenti con Keycloak in quanto non è l'opzione configurata",
|
||||
"server_keycloak_error2": "Errore: impossibile leggere i dati di configurazione Keycloak",
|
||||
"server_keycloak_error3": "Errore: impossibile recuperare gli utenti Keycloak: {1}",
|
||||
"server_keycloak_summary": "La sincronizzazione Keycloak ha trovato {1} utenti, {2} nuovi utenti aggiunti, {3} utenti con dati mancanti ignorati",
|
||||
"server_smtp_success": "Email inviata con successo",
|
||||
"server_smtp_test_subject": "Test SMTP di Documize Community",
|
||||
"server_smtp_test_body": "Questa è una email di prova da Documize Community utilizzando le impostazioni SMTP attuali.",
|
||||
"server_error_user": "Errore: impossibile recuperare gli utenti",
|
||||
"server_error_org": "Errore: impossibile ottenere il record dell'organizzazione",
|
||||
|
||||
"mail_template_click_here": "Clicca qui",
|
||||
"mail_template_sender": "Il tuo collega",
|
||||
"mail_template_approval": "{1} ti ha assegnato il ruolo di approvazione documento",
|
||||
"mail_template_approval_explain": "Ti è stato chiesto di approvare tutte le modifiche al seguente documento:",
|
||||
"mail_template_password": "La tua password temporanea:",
|
||||
"mail_template_user_invite": "{1} ti ha invitato a unirti a Documize Community",
|
||||
"mail_template_user_existing": "{1} ti ha invitato al suo account Documize Community",
|
||||
"mail_template_reset_password": "Richiesta reset password di Documize Community",
|
||||
"mail_template_shared": "{1} ha condiviso lo spazio {2} con te",
|
||||
"mail_template_invited": "{1} ha condiviso lo spazio {2} con te su Documize Community",
|
||||
"mail_template_approval_request": "{1} ha richiesto l'approvazione delle modifiche al documento",
|
||||
"mail_template_approval_request_explain": "Si prega di approvare le modifiche al documento intitolato {1}",
|
||||
"mail_template_approval_withdraw": "{1} ha ritirato la richiesta di approvazione delle modifiche al documento",
|
||||
"mail_template_approval_withdraw_explain": "{1} La richiesta di approvazione è stata ritirata per il documento",
|
||||
"mail_template_publish_explain": "Puoi pubblicare il documento {1} cambiando lo stato da Bozza a Pubblicato.",
|
||||
"mail_template_reviewer": "La revisione delle modifiche al documento è stata completata da {1}",
|
||||
"mail_template_approval_1": "La tua modifica non è stata pubblicata in quanto nessun revisore ha approvato la modifica.",
|
||||
"mail_template_approval_2": "La tua modifica non è stata pubblicata in quanto la maggioranza dei revisori non ha approvato la modifica.",
|
||||
"mail_template_approval_3": "La tua modifica non è stata pubblicata in quanto l'approvazione unanime non è stata raggiunta.",
|
||||
"mail_template_approval_4": "La tua modifica è stata pubblicata in quanto un revisore ha approvato la modifica.",
|
||||
"mail_template_approval_5": "La tua modifica è stata pubblicata in quanto la maggioranza dei revisori ha approvato la modifica.",
|
||||
"mail_template_approval_6": "La tua modifica è stata pubblicata in quanto è stata ottenuta un'approvazione unanime.",
|
||||
"mail_template_approval_7": "La tua modifica è ancora in fase di revisione e richiede l'approvazione di un altro revisore.",
|
||||
"mail_template_approval_8": "La tua modifica è ancora in fase di revisione e richiede l'approvazione della maggioranza dei revisori.",
|
||||
"mail_template_approval_9": "La tua modifica è ancora in fase di revisione e richiede un'approvazione unanime.",
|
||||
"mail_template_review_outcome": "{1} ha revisionato la tua modifica per il documento {2} e è stato segnato come {3}. {4}",
|
||||
"mail_template_action_read": "Si prega di leggere il documento {1} entro {2}.",
|
||||
"mail_template_action_feedback": "Si prega di fornire un feedback sul documento {1} entro {2}.",
|
||||
"mail_template_action_contribute": "Si prega di contribuire al contenuto del documento {1} entro {2}.",
|
||||
"mail_template_publish_request": "{1} ha richiesto la pubblicazione del documento",
|
||||
"mail_template_action_assigned": "{1} ti ha assegnato un'azione sul documento",
|
||||
"mail_template_action_done": "{1} ha completato l'azione sul tuo documento",
|
||||
"mail_template_action_read_done": "{1} ha letto il documento {2} (scadenza {3})",
|
||||
"mail_template_action_feedback_done": "{1} ha fornito un feedback per il documento {2} (scadenza {3})",
|
||||
"mail_template_action_contribute_done": "{1} ha contribuito al contenuto del documento {2} (scadenza {3})",
|
||||
"mail_template_share_doc": "{1} ha condiviso un documento con te",
|
||||
"mail_template_share_viewed": "{1} è stato visualizzato",
|
||||
"mail_template_feedback_received": "{1} ti ha inviato un feedback su {2}"
|
||||
}
|
||||
|
758
gui/public/i18n/ja-JP.json
Normal file
758
gui/public/i18n/ja-JP.json
Normal file
|
@ -0,0 +1,758 @@
|
|||
{
|
||||
"all": "すべて",
|
||||
"none": "なし",
|
||||
"never": "なし",
|
||||
"add": "追加",
|
||||
"added": "追加",
|
||||
"activate": "アクティブにする",
|
||||
"summary": "概要",
|
||||
"approve": "承認する",
|
||||
"authenticate": "認証する",
|
||||
"cancel": "キャンセル",
|
||||
"close": "閉じる",
|
||||
"copy": "コピー",
|
||||
"copied": "コピー",
|
||||
"delete": "削除",
|
||||
"deleted": "削除する",
|
||||
"remove": "削除",
|
||||
"duplicate": "複製",
|
||||
"duplicated": "複製された",
|
||||
"edit": "編集",
|
||||
"edited": "編集",
|
||||
"download": "ダウンロード",
|
||||
"upload": "アップロード",
|
||||
"uploaded": "アップロード済み",
|
||||
"import": "インポート",
|
||||
"export": "エクスポート",
|
||||
"exported": "エクスポート済み",
|
||||
"pdf": "PDF",
|
||||
"test": "テスト",
|
||||
"configure": "設定",
|
||||
"error": "エラー",
|
||||
"file": "ファイル",
|
||||
"insert": "挿入",
|
||||
"invite": "招待状",
|
||||
"message": "メッセージ",
|
||||
"join": "参加する",
|
||||
"leave": "退出",
|
||||
"login": "ログイン",
|
||||
"logout": "ログアウト",
|
||||
"authentication": "認証",
|
||||
"move": "移動",
|
||||
"moved": "移動した",
|
||||
"next": "次へ",
|
||||
"ok": "OK",
|
||||
"preview": "プレビュー",
|
||||
"preview_wait": "プレビューの生成...",
|
||||
"pdf_prepare": "PDFの準備",
|
||||
"publish": "発行する",
|
||||
"print": "印刷する",
|
||||
"reject": "却下",
|
||||
"rejected": "却下済み",
|
||||
"reply": "返信",
|
||||
"replied": "返信済み",
|
||||
"reset": "リセット",
|
||||
"request": "リクエスト",
|
||||
"requested": "リクエスト済み",
|
||||
"save": "保存",
|
||||
"saved": "保存済み",
|
||||
"search": "検索",
|
||||
"send": "送信",
|
||||
"share": "共有",
|
||||
"discard": "破棄する",
|
||||
"continue": "続ける",
|
||||
"code": "コード",
|
||||
"signin": "サインイン",
|
||||
"sort": "ソート",
|
||||
"sort_ascending": "昇順",
|
||||
"sort_descending": "降順",
|
||||
"sort_by_name": "名前",
|
||||
"sort_by_created": "作成日",
|
||||
"sort_by_revised": "最終更新日",
|
||||
"unassigned": "未設定",
|
||||
"update": "更新日",
|
||||
"updating": "更新中",
|
||||
"viewed": "閲覧中",
|
||||
"name": "名称",
|
||||
"description": "説明",
|
||||
"excerpt": "抜粋",
|
||||
"icon": "アイコン",
|
||||
"color": "カラー",
|
||||
"visibility": "視認性",
|
||||
"running": "実行中...",
|
||||
"firstname": "名(ファーストネーム)",
|
||||
"lastname": "姓(ラストネーム)",
|
||||
"email": "電子メール",
|
||||
"email_recipient": "受信者の電子メール",
|
||||
"password": "パスワード",
|
||||
"password_new": "新しいパスワード",
|
||||
"username": "ユーザー名",
|
||||
"user": "ユーザー名",
|
||||
"password_confirm": "パスワードの確認",
|
||||
"encryption": "暗号化",
|
||||
"notice": "お知らせ",
|
||||
"backup": "バックアップ",
|
||||
"restore": "リストア",
|
||||
"completed": "完了しました",
|
||||
"please_wait": "しばらくお待ちください。",
|
||||
"filter": "フィルター",
|
||||
"not_found": "見つかりません",
|
||||
"nothing_found": "何も見つかりません",
|
||||
"expand_collapse": "展開/折りたたみ",
|
||||
"options": "オプション",
|
||||
"settings": "設定方法",
|
||||
"about": "について",
|
||||
"meta": "メタデータ",
|
||||
"permissions": "アクセス権",
|
||||
"profile": "プロフィール",
|
||||
"go_top": "トップページへ",
|
||||
"help": "ヘルプ",
|
||||
"reference": "リファレンス",
|
||||
"references": "参考文献",
|
||||
"move_up": "上に移動",
|
||||
"move_down": "下に移動",
|
||||
"indent": "インデント",
|
||||
"outdent": "アウトデント",
|
||||
"default": "デフォルト",
|
||||
"no_undo": "元に戻すことができないので、注意してください。",
|
||||
"show_hide": "表示/非表示",
|
||||
"sent": "送信",
|
||||
"everyone": "全員",
|
||||
"ip": "IP",
|
||||
"event": "イベント",
|
||||
"when": "いつ",
|
||||
"last_seen": "最後に見たのは",
|
||||
"change": "変更",
|
||||
"no_access": "アクセス拒否",
|
||||
"drag_drop_reorder": "ドラッグ&ドロップで並び替え",
|
||||
"select": "選択",
|
||||
"locale": "ロケール",
|
||||
|
||||
"public": "公開",
|
||||
"public_explain": "公開 - 誰でも見ることができます。",
|
||||
"protected": "保護",
|
||||
"protected_explain": "保護 - アクセスは特定のユーザーに制限されます。",
|
||||
"personal": "個人",
|
||||
"personal_explain": "個人 - 自分だけが見ることができます",
|
||||
"label": "ラベル",
|
||||
"labels": "ラベル",
|
||||
"labels_none": "ラベルなし",
|
||||
"label_unclassified": "未分類",
|
||||
"draft": "下書き",
|
||||
"drafted": "ドラフト",
|
||||
"draft_explain": "ドラフト - 公開前に承認が必要、改訂履歴なし",
|
||||
"drafts": "下書き",
|
||||
"live": "ライブ",
|
||||
"live_explain": "ライブ - 作成時に公開されます。",
|
||||
"archived": "アーカイブ",
|
||||
"archived_explain": "アーカイブ - 誰にも公開されません。",
|
||||
"approved": "承認済み",
|
||||
"reverted": "元に戻す",
|
||||
"published": "公開",
|
||||
"space": "スペース",
|
||||
"spaces": "スペース",
|
||||
"category": "カテゴリ",
|
||||
"category_explain": "文書にカテゴリーを設定し、閲覧者を決定することができます。",
|
||||
"categories": "カテゴリ",
|
||||
"tag": "タグ",
|
||||
"tags": "タグ",
|
||||
"tag_rules": "最大{1}個のタグを指定可能 - 小文字、文字、数字、ハイフンのみ",
|
||||
"revisions": "リビジョン",
|
||||
"versions": "バージョン",
|
||||
"version": "バージョン",
|
||||
"versioned": "バージョン",
|
||||
"versions_explain": "同じコンテンツに複数のバージョンを作成 - ユーザーが閲覧するバージョンを選択可能",
|
||||
"change_control": "変更管理",
|
||||
"change_control_explain": "変更管理の方法を選択できます。",
|
||||
"pin": "ピン",
|
||||
"pinned": "ピン留め",
|
||||
"unpin": "ピン留め解除",
|
||||
"unpinned": "ピン留め解除",
|
||||
"blocks": "コンテンツブロック",
|
||||
"blocks_explain": "コンテンツブロックは、任意のドキュメントに挿入できる再利用可能なコンテンツです。",
|
||||
"block_delete_confirm": "この再利用可能なコンテンツブロックを本当に削除してもよろしいですか?",
|
||||
"actions": "操作方法",
|
||||
"activity": "アクティビティ",
|
||||
"activity_explain": "追加、閲覧、更新、承認などのユーザーアクティビティをレポートします。",
|
||||
"reports": "レポート",
|
||||
"content": "コンテンツ",
|
||||
"template": "テンプレート",
|
||||
"templates": "テンプレート",
|
||||
"document": "ドキュメント",
|
||||
"documents": "ドキュメント",
|
||||
"attachments": "添付ファイル",
|
||||
"history": "改訂履歴",
|
||||
"bookmark": "ブックマーク",
|
||||
"bookmarks": "ブックマーク",
|
||||
"bookmark_remove": "ブックマークの削除",
|
||||
"new": "新規作成",
|
||||
"copy_link": "リンクをコピー",
|
||||
"created": "作成",
|
||||
"markdown": "Markdownを受け入れる",
|
||||
"rename": "名前を変更する",
|
||||
"status": "ステータス",
|
||||
"expiry": "有効期限",
|
||||
"feedback": "フィードバック",
|
||||
"un_categorized": "未分類",
|
||||
|
||||
"toc": "目次",
|
||||
"new_canvas": "新しいキャンバス",
|
||||
"new_template": "テンプレートから",
|
||||
"new_import": "ファイルのインポート",
|
||||
"new_import_explain1": "クリックでファイルを選択、またはドラッグ&ドロップでファイルを取り込む",
|
||||
"new_import_explain2": ".doc、.docx、.md、.markdown",
|
||||
"new_content": "新しいコンテンツ",
|
||||
"export_html": "HTMLとして書き出す",
|
||||
"export_html_explain1": "すべてのスペースコンテンツをHTMLとしてエクスポートするか、カテゴリーを選択してエクスポートします。",
|
||||
"export_html_explain2": "すべてのスペースコンテンツは、1つの自己完結型HTMLファイルとしてエクスポートされます。",
|
||||
"import_convert": "{1}を変換中",
|
||||
"import_success": "{1}の変換に成功しました。",
|
||||
"add_recent": "最近追加されたもの",
|
||||
"update_recent": "最近更新された",
|
||||
"space_change": "他のスペースに移動する",
|
||||
"space_change_prompt": "スペースの選択",
|
||||
"space_new": "新しいスペース",
|
||||
"space_name": "スペース名",
|
||||
"space_name_rules": "文字と数字のみ",
|
||||
"space_description": "スペースの説明",
|
||||
"space_clone": "クローンスペース",
|
||||
"space_select": "スペースの選択",
|
||||
"space_delete": "スペースの削除",
|
||||
"space_delete_prompt": "スペース名を入力してください。",
|
||||
"space_delete_warn": "これにより、このスペース内のすべてのドキュメントとテンプレートが削除されます",
|
||||
"space_copy": "既存のスペースからテンプレート、権限、ドキュメントをコピーする",
|
||||
"space_copy_template": "テンプレートをコピー",
|
||||
"space_copy_permission": "パーミッションのコピー",
|
||||
"space_copy_document": "ドキュメントをコピーする",
|
||||
"space_empty_state": "このスペースにはまだドキュメントがありません",
|
||||
"space_lockout": "スペースの権限により、ドキュメントの閲覧や作成ができません",
|
||||
"space_invite_message": "{1}スペース({2}内)を共有し、ドキュメントを共同作成することができます。",
|
||||
"protection_none": "承認なしで変更可能",
|
||||
"protection_lock": "ロックされており、変更は許可されていません",
|
||||
"protection_review": "変更は公開前に承認が必要です",
|
||||
"template_published": "公開されたテンプレート",
|
||||
"block_explain": "コンテンツブロックは、あらゆるドキュメントに挿入可能な再利用可能なコンテンツを提供します。",
|
||||
"block_published": "発行済みブロック",
|
||||
"upload_attachment": "添付ファイルのアップロード",
|
||||
"content_revisions": "コンテンツのリビジョン",
|
||||
"content_revisions_explain": "以前のコンテンツの変更を確認し、編集をロールバックすることができます。",
|
||||
"move_documents": "ドキュメントの移動",
|
||||
"delete_documents": "ドキュメントの削除",
|
||||
"feedback_enable": "フィードバックの有効化",
|
||||
"feedback_prompt": "フィードバックのプロンプト",
|
||||
"feedback_prompt_hint": "ユーザーからのフィードバックを求めるプロンプトを入力",
|
||||
"feedback_prompt_explain": "プロンプトを指定する(例:これは役に立ちましたか?これは役に立ちましたか?必要なものは見つかりましたか?",
|
||||
"feedback_thanks": "フィードバックをありがとうございました。",
|
||||
"feedback_help_yes": "はい、ありがとうございました",
|
||||
"feedback_help_no": "そうでもない",
|
||||
"likes_prompt": "お役に立ちましたか?",
|
||||
"delete_confirm": "本当に削除しますか?",
|
||||
"category_assignment_summary": "1}ドキュメントに割り当てられ、{2}ユーザー/グループによって閲覧可能です。",
|
||||
"category_no_access": "このカテゴリには閲覧権限がありません",
|
||||
"category_default": "新規コンテンツの既定のカテゴリ",
|
||||
"category_default_explain": "新規作成されたドキュメントに自動的に適用されます",
|
||||
"category_delete_confirm": "本当にこのカテゴリを削除しますか?",
|
||||
"category_permissions": "カテゴリの権限",
|
||||
"category_permissions_explain": "カテゴリ内のドキュメントを閲覧できるユーザーを選択します",
|
||||
"category_none": "このスペースにはまだカテゴリがありません",
|
||||
|
||||
"approval_anybody": "任意の承認者の承認が必要",
|
||||
"approval_majority": "承認者の過半数の承認が必要",
|
||||
"approval_unanimous": "全承認者の全会一致が必要",
|
||||
"approval_pending": "変更待ち",
|
||||
"approval_awaiting": "承認待ち",
|
||||
"protection_type_open": "公開",
|
||||
"protection_type_protected": "保護されている",
|
||||
"protection_type_locked": "ロックされている",
|
||||
"doc_request_contribution": "投稿を依頼する",
|
||||
"doc_request_feedback": "フィードバックを要求する",
|
||||
"doc_request_read": "閲覧を希望する",
|
||||
"doc_request_publication": "公開をリクエストする",
|
||||
"doc_request_approval": "承認依頼",
|
||||
"doc_withdraw_approval": "リクエストの取り消し",
|
||||
"doc_withdraw_approval_reason": "説明文",
|
||||
"doc_withdraw_approval_reason_explain": "訂正や追加など、理由を説明する有用なメモ",
|
||||
"doc_review_publish": "変更点を確認し、承認してください。",
|
||||
"doc_review_discard": "この承認依頼を取り消したいのですが。",
|
||||
"doc_contribution_pending": "変更を保留しています",
|
||||
"doc_contribution_under_review": "承認リクエストはレビュー中です",
|
||||
"doc_contribution_rejected": "変更が却下されました",
|
||||
"doc_contribution_review": "変更の確認 ({1})",
|
||||
"doc_change_status": "{1} 変更が進行中、{2} レビュー待ち、{3} 不許可",
|
||||
"doc_approve_reject": "変更を承認/却下する",
|
||||
"doc_approve_method": "承認方法",
|
||||
"doc_approve_status": "承認状況",
|
||||
"doc_approver_status": "{1}件の承認と{2}件の却下、{3}人の承認者がこのレビューに関与しています。",
|
||||
"doc_publish": "このドキュメントを Draft から Live に移動してもらえますか?公開する準備ができました",
|
||||
"doc_category_explain": "このスペース内のコンテンツを整理するために、1つ以上のカテゴリーを割り当ててください。",
|
||||
"doc_action_request_ask": "依頼する",
|
||||
"doc_action_request_to": "をクリックします。",
|
||||
"doc_action_request_by": "変更する",
|
||||
"revision_none": "修正なし",
|
||||
"revision_restore": "セクションを復元する",
|
||||
"revision_restore_confirm": "このリビジョンを本当に復元しますか?",
|
||||
"template_save": "テンプレートとして保存",
|
||||
"template_name_explain": "ドキュメントの種類を示す良いテンプレート名",
|
||||
"template_desc_explain": "このテンプレートの用途を説明する",
|
||||
"print_explain": "すべての内容を印刷するか、セクションを選択して印刷するか",
|
||||
"doc_delete_confirm": "この文書を本当に削除しますか?",
|
||||
"attachment_delete": "添付ファイルを削除する",
|
||||
"attachment_delete_confirm": "この添付ファイルを削除してもよろしいですか?",
|
||||
"link_insert": "リンクの挿入",
|
||||
"link_type_section": "セクション",
|
||||
"link_type_section_explain": "この文書内のコンテンツにリンクします",
|
||||
"link_type_attachment": "添付ファイル",
|
||||
"link_type_attachment_explain": "このドキュメント内の添付ファイルへのリンク",
|
||||
"link_type_search": "検索",
|
||||
"link_type_search_explain": "文書名、内容、添付ファイル名",
|
||||
"link_type_network": "ネットワーク",
|
||||
"link_type_network_explain": "ネットワークドライブ/共有/フォルダの場所を指定します。",
|
||||
"link_type_network_example": "例://share/folder",
|
||||
"discard_changes": "変更の破棄",
|
||||
"discard_confirm": "編集を続けるか、それとも変更を破棄するか?",
|
||||
"share_expire_2": "2日以内",
|
||||
"share_expire_7": "7日以内",
|
||||
"share_expire_14": "14日以内",
|
||||
"share_expire_30": "30日以内",
|
||||
"share_expire_60": "60日以内",
|
||||
"share_expire_90": "90日以内",
|
||||
|
||||
"actions_mine": "あなたに割り当てられたアクション",
|
||||
"actions_none": "アクションはありません",
|
||||
"actions_due": "期限付き",
|
||||
"actions_see_note": "メモを読む",
|
||||
"actions_mark_complete": "完了とする",
|
||||
"actions_completed": "完了",
|
||||
"actions_see_more": "{1} 完了した行動 →",
|
||||
"actions_requested": "あなたが他人に指示した行動",
|
||||
"actions_requested_none": "依頼はしていません",
|
||||
"actions_requested_more": "最近完了した依頼がある → {1}依頼",
|
||||
"actions_requested_complete": "{1}依頼が完了した →",
|
||||
"activity_period": "期間",
|
||||
"activity_filter_past": "過去",
|
||||
"activity_filter_days": "日数",
|
||||
"activity_filter_for": "24時間",
|
||||
"audit_24": "24時間",
|
||||
"audit_7": "7日間",
|
||||
"audit_14": "14日間",
|
||||
"audit_30": "30日",
|
||||
"audit_90": "90日",
|
||||
"chat_leave_comment": "コメントを残す",
|
||||
"chat_applies_to": "適用対象",
|
||||
"chat_delete_confirm": "本当にこのコメントを削除しますか?",
|
||||
"chat_reply_delete_confirm": "本当にこの返信を削除しますか?",
|
||||
"doc_secure_share": "安全な外部リンクで共有する",
|
||||
"doc_secure_shared_by": "共有者",
|
||||
"doc_version_viewed": "バージョン名変更",
|
||||
"doc_version_remove": "バージョン解除",
|
||||
"doc_version_create": "ドキュメントのバージョンを作成する",
|
||||
"doc_version_explain": "バージョンとは、ドキュメントに割り当てられるもので、バージョンごとに異なるドキュメントとなります。",
|
||||
"doc_version_label": "バージョンラベル",
|
||||
"doc_version_label_explain": "例:1.0、v1.0、バージョン1、2018.1リリース",
|
||||
"doc_version_this": "このドキュメントの新しいバージョンを作成する",
|
||||
"doc_version_select": "または他のドキュメントを選択",
|
||||
"doc_version_assign": "このドキュメントにバージョンを割り当てる",
|
||||
"doc_version_dropdown": "<他のドキュメントにバージョンを割り当てる>を選択",
|
||||
"doc_version_remove_confirm": "本当にこのバージョンとその内容をすべて削除しますか?",
|
||||
"doc_version_remove_name": "以下に文書名を入力して確認してください。",
|
||||
"doc_version_unversion": "バージョン解除を行うと、そのドキュメントは全ての内容を保持したまま独立します。",
|
||||
"doc_version_unversion_confirm": "本当にこの文書のバージョンを解除しますか?",
|
||||
"archived_content": "アーカイブされたコンテンツ",
|
||||
"archived_content_explain": "アーカイブされたコンテンツをライブとしてマーク",
|
||||
"unarchive_content": "アーカイブを解除する",
|
||||
|
||||
"document_permissions": "ドキュメントのアクセス権",
|
||||
"space_permissions": "スペースの権限",
|
||||
"space_permissions_explain": "ユーザーやグループに権限を与え、このスペースに新しいユーザーを招待することができます。",
|
||||
"space_permission_view": "閲覧",
|
||||
"space_permission_view_explain": "このスペースのコンテンツを見ることができます。",
|
||||
"space_permission_manage": "管理",
|
||||
"space_permission_manage_explain": "削除を除く、スペースのすべての機能を管理できます。",
|
||||
"space_permission_owner": "所有者",
|
||||
"space_permission_owner_explain": "スペースの管理・削除",
|
||||
"space_permission_doc_create": "作成",
|
||||
"space_permission_doc_create_explain": "スペースに新しいドキュメントを作成することができます",
|
||||
"space_permission_doc_edit": "編集",
|
||||
"space_permission_doc_edit_explain": "ドキュメントの内容を変更することができます",
|
||||
"space_permission_doc_delete": "削除",
|
||||
"space_permission_doc_delete_explain": "スペースからドキュメントを削除することができます",
|
||||
"space_permission_doc_move": "移動",
|
||||
"space_permission_doc_move_explain": "このスペースから他のスペースにドキュメントを移動することができます",
|
||||
"space_permission_doc_copy": "コピー",
|
||||
"space_permission_doc_copy_explain": "ドキュメントを複製することができます",
|
||||
"space_permission_doc_template": "テンプレート",
|
||||
"space_permission_doc_template_explain": "ドキュメントのテンプレートを作成し、公開することができます",
|
||||
"space_permission_doc_approval": "承認",
|
||||
"space_permission_doc_approval_explain": "(1)文書の変更を承認または拒否できる (2)文書をドラフトから本番に移行できる",
|
||||
"space_permission_doc_draft": "下書き",
|
||||
"space_permission_doc_draft_explain": "ドラフトとしてマークされたドキュメントの表示と作業が可能",
|
||||
"space_permission_doc_version": "バージョン",
|
||||
"space_permission_doc_version_explain": "文書のバージョンを作成し、それらを相互にリンクすることができます",
|
||||
"space_permission_add_user": "このスペースにユーザーを追加する",
|
||||
"space_permission_invite_user": "このスペースにユーザーを招待する",
|
||||
"space_permission_invite_explain": "複数のメールアドレスをカンマで区切る",
|
||||
|
||||
"section_insert": "セクションの挿入",
|
||||
"section_insert_here": "ここにセクションを挿入",
|
||||
"section_copy_explain": "このセクションとすべてのネストされたセクションは、選択されたドキュメントにコピーされます。",
|
||||
"section_move_explain": "このセクションとすべてのネストされたセクションは、選択中のドキュメントに移動されます。",
|
||||
"section_delete": "このセクションは本当に削除してよろしいですか?",
|
||||
"section_delete_children": "子セクションも削除する",
|
||||
"section_publish": "再利用可能なコンテンツブロックを公開する",
|
||||
"section_publish_name_explain": "再利用可能なコンテンツ ブロックの短いタイトルを指定します。",
|
||||
"section_publish_desc_explain": "再利用可能なコンテンツ ブロックを他の人が理解するのに役立つ短い説明",
|
||||
"section_airtable": "Airtable",
|
||||
"section_airtable_explain": "一部はスプレッドシート、一部はデータベース、そして完全に柔軟 (https://airtable.com)",
|
||||
"section_airtable_code": "Airtableの埋め込みコード",
|
||||
"section_code_tip": "コードスニペットを説明する簡潔な名前",
|
||||
"section_drawio": "ダイアグラムネット",
|
||||
"section_drawio_explain": "フローチャート、プロセス図、組織図、UML、ER図、ネットワーク図、その他を作成する (https://www.diagrams.net)",
|
||||
"section_iframe": "iFrame",
|
||||
"section_iframe_explain": "iFrameを埋め込む",
|
||||
"section_iframe_code": "iFrameの埋め込みコード",
|
||||
"section_gemini": "Gemini",
|
||||
"section_gemini_explain": "Geminiエンタープライズ問題追跡およびヘルプデスクソフトウェア (https://www.countersoft.com)",
|
||||
"section_gemini_url": "Gemini URL",
|
||||
"section_gemini_url_explain": "例: https://helpdesk.countersoft.com",
|
||||
"section_gemini_key": "APIキー (ユーザープロファイルから)",
|
||||
"section_gemini_workspace": "ワークスペース",
|
||||
"section_jira": "Jira ソフトウェア",
|
||||
"section_jira_explain": "Jira は課題追跡とアジャイルソフトウェアを提供します。",
|
||||
"section_jira_admin": "使用する前に、Documize Community の管理者が Jira 接続の詳細を提供する必要があります。",
|
||||
"section_jira_no_auth": "Jira コネクタが認証されていません。",
|
||||
"section_papertrail": "Papertrail",
|
||||
"section_papertrail_explain": "クラウドベースのログを表示します (https://papertrailapp.com)",
|
||||
"section_papertrail_key": "Papertrail API キー",
|
||||
"section_papertrail_search": "検索クエリ",
|
||||
"section_papertrail_search_explain": "表示したいログを指定する 例:bob OR (\"some phrase\" AND sally)",
|
||||
"section_papertrail_max": "最大表示件数",
|
||||
"section_papertrail_max_explain": "何件のログを表示するか?",
|
||||
"section_papertrail_group": "グループ",
|
||||
"section_papertrail_group_explain": "Papertrailグループ(オプション",
|
||||
"section_pdf": "PDFビューア",
|
||||
"section_pdf_upload_explain": "最初にアップロードされたPDFが使用されます",
|
||||
"section_pdf_height": "プレビューの高さ",
|
||||
"section_pdf_height_explain": "PDFプレビューの高さは?",
|
||||
"section_pdf_start": "開始ページ",
|
||||
"section_pdf_start_explain": "最初に表示されるページ",
|
||||
"section_pdf_sidebar": "サイドバー",
|
||||
"section_pdf_sidebar_explain": "オプションで、サイドバーの内容を設定することができます",
|
||||
"section_pdf_sidebar_none": "なし",
|
||||
"section_pdf_sidebar_bookmark": "ブックマーク",
|
||||
"section_pdf_sidebar_thumbnail": "サムネイル",
|
||||
"section_plantuml": "プラントUML",
|
||||
"section_plantuml_explain": "プレーンテキスト言語から UML 図を作成する (http://plantuml.com)",
|
||||
"section_plantuml_link": "PlantUMLダイアグラム",
|
||||
"section_plantuml_type_sequence": "シーケンス",
|
||||
"section_plantuml_type_usecase": "ユースケース",
|
||||
"section_plantuml_type_class": "クラス",
|
||||
"section_plantuml_type_activity": "アクティビティ",
|
||||
"section_plantuml_type_activity2": "アクティビティ(新シンタックス)",
|
||||
"section_plantuml_type_component": "コンポーネント",
|
||||
"section_plantuml_type_state": "状態",
|
||||
"section_tabular_import_csv": "CSVインポート",
|
||||
"section_tabular_csv": "CSVからテーブルへ",
|
||||
"section_tabular_warn": "注意:既存のテーブルのデータは置き換えられます",
|
||||
"section_tabular_paste": "CSVデータの貼り付け",
|
||||
"section_tabular_format": "一般的なデリミタが使用可能",
|
||||
"section_tabular_first_row": "1行目のヘッダ",
|
||||
"section_tabular_first_row_explain": "最初の行にヘッダーが含まれる場合に有効",
|
||||
"section_trello": "Trello",
|
||||
"section_trello_explain": "Trelloはプロジェクトを管理し、あらゆるものを整理するためのビジュアルな方法です(https://trello.com)",
|
||||
"section_trello_none": "共有するチームボードがない - 個人用ボードが表示されない",
|
||||
"section_trello_admin": "Trelloを使用する前に、Documize Communityの管理者がTrelloを設定する必要があります。",
|
||||
"section_trello_board": "ボード",
|
||||
"section_trello_list": "リスト",
|
||||
|
||||
"login_cas": "CASで認証中...",
|
||||
"login_cass_error": "CAS認証に失敗しました。",
|
||||
"login_keycloak": "Keycloakで認証する...",
|
||||
"login_keycloak_error": "Keycloakの認証に失敗しました。",
|
||||
"login_invalid": "無効な認証情報",
|
||||
"forgot_password": "パスワードをお忘れの方",
|
||||
"reset_password": "パスワードのリセット",
|
||||
"reset_password_next": "ありがとうございます。メールに記載されている指示を確認してください。",
|
||||
"password_strong": "強力なパスワードを選択する",
|
||||
"password_match": "パスワードは一致させる必要があります",
|
||||
"welcome": "Documize へようこそ",
|
||||
"welcome_explain": "アカウントを設定し、使い始めましょう",
|
||||
"profile_explain": "プロフィールとパスワードの管理",
|
||||
"search_hint": "キーワード、タグ",
|
||||
"search_too_short": "検索クエリが短すぎる",
|
||||
"search_doc_name": "ドキュメント名",
|
||||
"search_doc_content": "文書内容",
|
||||
"search_tag_name": "タグ名",
|
||||
"search_attachment_name": "添付ファイル名",
|
||||
"search_example_title": "クエリーの例",
|
||||
"search_explain": "キーワードと演算子でコンテンツを検索する",
|
||||
"search_example1": "2つの単語のうち少なくとも1つを含む結果を表示する",
|
||||
"search_example2": "両方の単語を含む結果を表示",
|
||||
"search_example3": "apple」を含むが「macintosh」も含む結果を上位表示する。",
|
||||
"search_example4": "apple \"を含むが \"macintosh \"を含まない結果を表示する",
|
||||
"search_example5": "apple \"と \"turnover\"、または \"apple \"と \"strudel\"(順不同)を含むが、\"apple turnover \"が \"apple strudel \"より上位にランクされている検索結果を表示する。",
|
||||
"search_example6": "\"apple\"、\"apples\"、\"applesauce\"、\"applet \"などの単語を含む結果を表示する。",
|
||||
"search_example7": "いくつかの言葉」を正確に含む結果を表示する(たとえば、「いくつかの知恵の言葉」は含むが「いくつかのノイズの言葉」は含まない行など)",
|
||||
"search_example8": "どちらかの単語を含む結果を表示",
|
||||
"search_example9": "google\"、\"apple \"または \"microsoft \"を含み、\"ibm \"を含まない結果を表示する。",
|
||||
"search_example10": "\"applesauce \"や \"applet \"など、\"apple \"で始まる単語を含む結果を表示します。",
|
||||
"space_density_complete": "完全",
|
||||
"space_density_comfort": "快適さ",
|
||||
"space_density_compact": "コンパクト",
|
||||
|
||||
"backup_explain1": "Documize Community はマルチテナントアプリケーションで、同じ実行ファイル/データベースを使用して 'tech.mycompany.com' と 'sales.mycompany.com' の両方を実行することができます。Documize Community グローバル管理者として、すべてのテナントにわたる完全なシステム全体のバックアップを実行することになりす,。Documize Community テナント管理者は、テナントレベルのバックアップを実行するためにログインすることができます(例:marketing.mycompany.com)。",
|
||||
"backup_explain2": "Documize Community はマルチテナントのアプリケーションであり、tech.mycompany.com と sales.mycompany.com の両方が同じ実行ファイル/データベースを使用して実行されるようになっています。Documize Community グローバル管理者は、すべてのテナントでシステム全体のバックアップを実行することになりま,すDocumize Community テナント管理者として、テナントレベルのバックアップを実行することができます(例:marketing.mycompany.com)。",
|
||||
"backup_explain3": "バックアップ処理の完了には数分かかることがあります。バックアップ処理の実行中はしばらくお待ちください。",
|
||||
"backup_retain": "バックアップファイルをサーバーに保存する",
|
||||
"backup_running": "バックアップ実行中、お待ちください...",
|
||||
"backup_tenant": "テナントのバックアップ",
|
||||
"backup_system": "バックアップシステム",
|
||||
"backup_failed": "バックアップに失敗しました -- サーバーのログを確認してください",
|
||||
"backup_success": "バックアップ成功",
|
||||
"backup_start": "バックアップの開始",
|
||||
"backup_run": "バックアップの実行",
|
||||
"restore_explain1": "システムバックアップからの復元は、空のDocumize Communityデータベースに対してのみ実行する必要があります。",
|
||||
"restore_explain2": "リストア操作により、ユーザー、グループ、パーミッション、スペース、カテゴリー、コンテンツが再作成されます。",
|
||||
"restore_explain3": "リストア処理の完了には数分かかる場合がありますので、リストア処理中はしばらくお待ちください。",
|
||||
"restore_select_file": "バックアップファイルの選択",
|
||||
"restore_running": "お待ちください、リストア実行中です。",
|
||||
"restore_failed": "復元に失敗しました -- サーバーログを確認してください",
|
||||
"restore_success": "リストア完了 -- ブラウザを再起動し、ログインしてください。",
|
||||
"restore_confirm": "リストアの確認",
|
||||
"restore_confirm_input": "RESTORE と入力して処理を開始してください。",
|
||||
"restore_warn": "空の Documize Community インスタンスにのみリストアする必要があります。",
|
||||
"changelog_available": "製品のアップデートが可能です。",
|
||||
"changelog_guidance": "アップグレードするには、既存のバイナリを置き換え、Documize Community を再起動してください。",
|
||||
"customize_name": "サイト名",
|
||||
"customize_name_explain": "この Documize Community インスタンスの短いタイトルを入力してください。",
|
||||
"customize_message": "サイトメッセージ",
|
||||
"customize_message_explain": "この Documize Community インスタンスを説明する短いメッセージを入力します。",
|
||||
"customize_theme": "サイトのテーマ",
|
||||
"customize_logo": "サイトのロゴ",
|
||||
"customize_logo_default": "デフォルトを使用",
|
||||
"customize_logo_upload": "カスタムをアップロード",
|
||||
"customize_logo_explain": "小さなロゴ(例:64px x 64px)をアップロードすることができます。",
|
||||
"customize_subdomain": "サイトURLサブドメイン",
|
||||
"customize_subdomain_explain": "docs.example.org \"でホストしている場合、サブドメインは \"docs \"に設定する必要があります。",
|
||||
"customize_anon": "匿名ユーザーが閲覧可能なパブリックスペース",
|
||||
"customize_anon_explain": "認証されていないサイト訪問者とコンテンツを共有します。",
|
||||
"customize_conversion_url": "コンバージョンサービスURL",
|
||||
"customize_conversion_explain": "インポート/エクスポートを処理するためのエンドポイント",
|
||||
"customize_tags": "ドキュメントあたりの最大タグ数",
|
||||
"customize_tags_explain": "1つのドキュメントに付けられるタグの数(3~10個程度)",
|
||||
"integration_jira_url": "URL",
|
||||
"integration_jira_url_explain": "Jira インスタンスの完全修飾ドメイン名 (例: http://jira.example.org)",
|
||||
"integration_jira_username": "ユーザー名",
|
||||
"integration_jira_username_explain": "Jira ログインユーザー名/E メール",
|
||||
"integration_jira_password": "パスワード",
|
||||
"integration_jira_password_explain": "Atlassian Cloud を使用している場合は API トークン、Jira をセルフホスティングしている場合はパスワードを入力します。",
|
||||
"integration_trello_appkey": "アプリキー",
|
||||
"search_reindex": "検索インデックスの再構築には最大で 30 分かかる場合があります。",
|
||||
"search_reindex_rebuild": "再構築",
|
||||
"search_reindex_start": "検索インデックスの再構築を開始",
|
||||
"search_reindex_finish": "検索インデックスの再構築が完了しました",
|
||||
"smtp_host": "ホスト",
|
||||
"smtp_host_explain": "例:my.host.com",
|
||||
"smtp_port": "ポート",
|
||||
"smtp_port_explain": "例:587",
|
||||
"smtp_username": "ユーザー名",
|
||||
"smtp_username_explain": "例:SMTPサーバーのログインユーザー名",
|
||||
"smtp_password": "パスワード",
|
||||
"smtp_password_explain": "例:SMTPサーバーのログインパスワード",
|
||||
"smtp_sender_email": "送信者メールアドレス",
|
||||
"smtp_sender_email_explain": "例)user@example.org",
|
||||
"smtp_sender_name": "送信者名",
|
||||
"smtp_sender_name_explain": "例:Documize",
|
||||
"smtp_fqdn": "送信者サーバーの完全修飾ドメイン名",
|
||||
"smtp_fqdn_explain": "(オプション) SMTPは有効なドメイン名を要求することができます、例えば docs.example.org",
|
||||
"smtp_anon_auth": "匿名認証 (認証情報を無視する)",
|
||||
"smtp_base64": "認証情報をBase64エンコードする",
|
||||
"smtp_ssl": "SSLを使用する",
|
||||
"smtp_save_test": "保存とテスト",
|
||||
"smtp_sent_test_email": "テストメールを送信する",
|
||||
"smtp_missing": "メールサーバーの設定",
|
||||
"space_admin_export": "すべてのコンテンツをエクスポートする",
|
||||
"space_admin_export_running": "エクスポート実行中....",
|
||||
"space_admin_make_owner": "自分をオーナーとして追加する",
|
||||
"space_admin_empty": "管理する共有スペースがない",
|
||||
"space_admin_delete_title": "スペースの削除",
|
||||
"space_admin_delete_check": "このスペースとすべてのドキュメントを本当に削除しますか?",
|
||||
"space_admin_confirm": "確認のため、スペース名を入力してください。",
|
||||
"space_admin_confirm_explain": "これにより、このスペース内のすべてのドキュメントとテンプレートが削除されます",
|
||||
"label_add": "ラベルの追加",
|
||||
"label_update": "ラベルの更新",
|
||||
"label_delete": "ラベルの削除",
|
||||
"label_delete_confirm": "本当にラベル{1}を削除しますか?",
|
||||
"user_admin_add": "ユーザーの追加",
|
||||
"user_admin_bulk": "一括アップロード",
|
||||
"user_admin_bulk_format": "カンマ区切りリスト: 名, 姓, 電子メール",
|
||||
"group_add": "グループ追加",
|
||||
"group_name_explain": "グループ名を入力(例:Managers, Developers, Acme Team",
|
||||
"group_member_add": "メンバーの追加",
|
||||
"group_member_remove": "メンバーの削除",
|
||||
"group_delete": "グループの削除",
|
||||
"group_delete_confirm": "本当にこのグループを削除しますか?",
|
||||
"group_delete_name": "確認のため、グループ名を入力してください。",
|
||||
"group_delete_name_explain": "この操作を行うと、グループのメンバー情報および関連する権限が削除されます。",
|
||||
"group_none": "グループなし",
|
||||
"group_edit": "グループの編集",
|
||||
"find_user": "ユーザー検索",
|
||||
"find_user_syntax": "名前、メールアドレスの検索",
|
||||
"user_max_display": "表示するユーザーの最大数",
|
||||
"user_assign_group": "ユーザーグループの割り当て",
|
||||
"user_delete_confirm": "本当にユーザー{1}を削除しますか?",
|
||||
"user_selected_delete_confirm": "選択したユーザーを本当に削除しますか?",
|
||||
"user_delete": "ユーザーを削除する",
|
||||
"permission_spaces": "スペース",
|
||||
"permission_spaces_explain": "個人用、共有用のスペースを追加することができます。",
|
||||
"permission_visible": "可視化",
|
||||
"permission_visible_explain": "ユーザーやグループの名前を表示できます。顧客やパートナーなどの外部ユーザーには表示しないようにできます。",
|
||||
"permission_admin": "管理者",
|
||||
"permission_admin_explain": "この画面のように、Documize Communityのすべての側面を管理することができます。",
|
||||
"permission_analytics": "分析機能",
|
||||
"permission_analytics_explain": "分析レポートを表示することができます。",
|
||||
"permission_active": "アクティブ",
|
||||
"permission_active_explain": "Documize Communityにログインして使用することができます。",
|
||||
"auth_role_space": "スペースの作成が可能",
|
||||
"auth_disable_logout": "ログアウトを無効にする",
|
||||
"auth_dual_login": "デュアルログイン",
|
||||
"auth_dual_login_explain": "LDAP経由のログインと通常のメール/パスワードによるログインが可能(LDAPのテストに有効)",
|
||||
"auth_email_password": "内蔵のメール/パスワード",
|
||||
"auth_connect_keycloak": "認証サーバーへの接続",
|
||||
"auth_connect_ldap": "LDAP/Active Directoryへの接続",
|
||||
"auth_connect_cas": "セントラル認証サーバーへの接続",
|
||||
"auth_keycloak_running": "Keycloakユーザー同期実行中...",
|
||||
"auth_keycloak_sync": "Keycloakとの同期",
|
||||
"auth_ldap_running": "LDAPユーザー同期中...",
|
||||
"auth_ldap_sync": "LDAPと同期",
|
||||
"auth_keycloak_url": "キーロック・サーバーのURL",
|
||||
"auth_keycloak_realm": "キーシクロークの領域",
|
||||
"auth_keycloak_pk": "キーシクロークのレルム公開鍵",
|
||||
"auth_keycloak_pk_explain": "Realm Settings > KeysからRSA Public Keyをコピーします。",
|
||||
"auth_keycloak_oidc": "キークロークOIDCクライアントID",
|
||||
"auth_keycloak_group": "キークローク・グループID(オプション)",
|
||||
"auth_keycloak_group_explain": "特定のグループ(例:'Documize Community Users')内のユーザーを同期したい場合、グループIDを入力してください(例:511d8b61-1ec8-45f6-bc8d-5de64d54c9d2)",
|
||||
"auth_keycloak_username": "Keycloakユーザー名",
|
||||
"auth_keycloak_username_explain": "Keycloakと接続し、ユーザーをDocumize Communityと同期するために使用します(マスターレルムの下でユーザーを作成し、上記で指定したレルムに対して「view-users」ロールを割り当ててください)。",
|
||||
"auth_keycloak_password": "キーロックのパスワード",
|
||||
"auth_keycloak_password_explain": "Keycloak と接続し、ユーザーを Documize コミュニティと同期させるために使用されます。",
|
||||
"auth_ldap_server": "LDAPサーバー",
|
||||
"auth_ldap_server_explain": "IPまたはホストアドレス、例:ldap.example.org、127.0.0.1",
|
||||
"auth_ldap_port": "LDAPサーバーのポート",
|
||||
"auth_ldap_port_explain": "ポート番号、例:389",
|
||||
"auth_ldap_base": "ベースDN",
|
||||
"auth_ldap_base_explain": "検索フィルターの始点、例: ou=users,dc=example,dc=com",
|
||||
"auth_ldap_bind": "バインドDN",
|
||||
"auth_ldap_bind_explain": "LDAPサーバーのログイン認証情報",
|
||||
"auth_ldap_password": "バインドパスワード",
|
||||
"auth_ldap_filter_user": "ユーザーフィルター",
|
||||
"auth_ldap_filter_user_explain1": "ユーザーを見つけるための検索フィルター、例: (|(objectClass=person)(objectClass=user)(objectClass=inetOrgPerson))",
|
||||
"auth_ldap_filter_user_explain2": "ユーザ・フィルタ、グループ・フィルタの指定",
|
||||
"auth_ldap_filter_group": "グループフィルター",
|
||||
"auth_ldap_filter_group_explain": "グループ経由のユーザを検索するためのフィルタ (&(objectClass=group)(|(cn=ship_crew)(cn=admin_staff))",
|
||||
"auth_ldap_rdn": "ユーザー属性RDN",
|
||||
"auth_ldap_rdn_explain1": "ユーザー名/ログイン属性、例:LDAPのuid、Active DirectoryのsAMAccountName",
|
||||
"auth_ldap_rdn_explain2": "ユーザーフィルター使用時にデータを取得するために使用されるユーザー属性",
|
||||
"auth_ldap_firstname": "ユーザ属性 Firstname",
|
||||
"auth_ldap_firstname_explain": "givenNameのようなFirstname属性",
|
||||
"auth_ldap_lastname": "ユーザー属性 Lastname",
|
||||
"auth_ldap_lastname_explain": "snなどのLastname属性",
|
||||
"auth_ldap_email": "User Attribute Email(ユーザ属性",
|
||||
"auth_ldap_email_explain": "電子メール属性,例:mail",
|
||||
"auth_ldap_group": "グループ属性 Member",
|
||||
"auth_ldap_group_explain1": "グループメンバー個人を特定するための属性。",
|
||||
"auth_ldap_group_explain2": "グループフィルター使用時にデータを取得するために使用されるグループ属性",
|
||||
"auth_ldap_preview": "LDAPプレビュー",
|
||||
"auth_ldap_preview_result": "接続に成功し、{1}人のユーザが見つかりました。",
|
||||
"auth_ldap_preview_error": "接続不可",
|
||||
"auth_cas_url": "CASサーバーのURL",
|
||||
"auth_cas_url_explain": "例)http://localhost:8888/auth",
|
||||
"auth_cas_back_url": "Documize CASのURL",
|
||||
"auth_cas_back_url_explain": "例)http://Documize-URL/auth/cas",
|
||||
"administration": "管理部門",
|
||||
"admin_general": "一般",
|
||||
"admin_general_explain": "Documize Community をカスタマイズするためのオプションです。",
|
||||
"admin_user_management": "ユーザー管理",
|
||||
"admin_user_management_explain": "基本情報、パスワード、アクセス権の管理",
|
||||
"admin_user_groups": "ユーザーグループ",
|
||||
"admin_user_groups_explain": "ユーザーと権限の管理を容易にするためのグループを定義",
|
||||
"admin_integrations": "統合機能",
|
||||
"admin_integrations_explain": "サードパーティとの統合を有効にし、設定する",
|
||||
"admin_mail_server": "メールサーバー",
|
||||
"admin_mail_server_explain": "ユーザーの招待メールや通知メールの送信に必要なメールサーバーの詳細設定",
|
||||
"admin_audit_log": "監査ログ",
|
||||
"admin_backup": "バックアップとリストア",
|
||||
"admin_backup_explain": "すべてのコンテンツを自己完結型の単一のZIPファイルにエクスポートします。",
|
||||
"admin_billing": "課金",
|
||||
"admin_changelog": "変更履歴",
|
||||
"admin_auth_explain": "ユーザー認証プロバイダーの選択 - Documize, Redhat Keycloak, LDAP/AD, Central Authentication Server",
|
||||
"admin_spaces_explain": "スペースの削除、共有スペースと孤立したスペースの所有権の取得",
|
||||
"admin_labels_explain": "ビジュアルラベルによるスペースのグループ化とナビゲート",
|
||||
"admin_search_explain": "検索インデックスの再構築",
|
||||
"setup_default_message": "Documize Communityインスタンスには、弊社のすべてのドキュメントが含まれています。",
|
||||
"get_in_touch": "お問い合わせ",
|
||||
"product_feedback": "製品のアイデア、提案、またはフィードバックがありますか?",
|
||||
"product_news": "製品ニュース",
|
||||
"product_news_explain": "最新の製品ニュースおよびアップデート",
|
||||
"product_update": "更新情報",
|
||||
"product_whats_new": "新着情報",
|
||||
"product_activation_key_missing": "アクティベーション・キーの紛失",
|
||||
"account_update": "アカウントの更新",
|
||||
"404": "そのページは見つかりませんでした。",
|
||||
"404_explain": "お探しのコンテンツは閲覧できない状態かもしれません",
|
||||
"close_account": "Documize アカウントを閉じてください。",
|
||||
"third_party": "Documize Community は、サードパーティのオープンソースライブラリおよびコンポーネントを使用しています。",
|
||||
|
||||
"server_ldap_error1": "エラー: 設定されたオプションでないため、LDAPによるユーザー同期をスキップする",
|
||||
"server_ldap_error2": "エラー: LDAP設定データを読み込めません",
|
||||
"server_ldap_error3": "エラー: LDAPユーザーをフェッチできません。{1}",
|
||||
"server_ldap_complete": "LDAPサーバーとの同期が完了しました",
|
||||
"server_ldap_summary": "LDAP同期で{1}人のユーザーを発見、{2}人の新規ユーザーを追加、{3}人のデータ欠損を無視",
|
||||
"server_keycloak_error1": "エラー: 設定されたオプションでないため、Keycloakとのユーザー同期をスキップする",
|
||||
"server_keycloak_error2": "エラー: Keycloakの設定データを読み込めません",
|
||||
"server_keycloak_error3": "エラー: Keycloakユーザーをフェッチできません。{1}",
|
||||
"server_keycloak_summary": "Keycloak sync found {1} users, {2} new users added, {3} users with missing data ignored.",
|
||||
"server_smtp_success": "メール送信成功",
|
||||
"server_smtp_test_subject": "Documize コミュニティ SMTP テスト",
|
||||
"server_smtp_test_body": "これは、現在の SMTP 設定を使用した Documize Community からのテスト電子メールです。",
|
||||
"server_error_user": "エラー: ユーザーを取得できません",
|
||||
"server_error_org": "エラー: 組織レコードを取得できません",
|
||||
|
||||
"mail_template_click_here": "ここをクリック",
|
||||
"mail_template_sender": "あなたの同僚",
|
||||
"mail_template_approval": "{1} があなたに文書承認の役割を与えました。",
|
||||
"mail_template_approval_explain": "次の文書に対するすべての変更を承認するよう依頼されました。",
|
||||
"mail_template_password": "あなたの一時的なパスワードです。",
|
||||
"mail_template_user_invite": "{1} があなたを Documize コミュニティに招待しました。",
|
||||
"mail_template_user_existing": "{1} がお客様を Documize コミュニティ アカウントに招待しました。",
|
||||
"mail_template_reset_password": "あなたの Documize Community パスワード リセット リクエスト",
|
||||
"mail_template_shared": "{1} はスペース {2} をあなたと共有しています。",
|
||||
"mail_template_invited": "{1} は Documize Community でスペース {2} を共有しています。",
|
||||
"mail_template_approval_request": "{1} がドキュメントの変更承認をリクエストしました",
|
||||
"mail_template_approval_request_explain": "1} というタイトルのドキュメントへの変更を承認してください。",
|
||||
"mail_template_approval_withdraw": "{1} はドキュメント変更の承認要求を取り下げました",
|
||||
"mail_template_approval_withdraw_explain": "{1} ドキュメントに対する承認要求が取り下げられました",
|
||||
"mail_template_publish_explain": "ドキュメント{1}のステータスをドラフトからライブに変更することで公開することができます。",
|
||||
"mail_template_reviewer": "ドキュメント変更のレビューが完了しました{1}。",
|
||||
"mail_template_approval_1": "レビューアが変更を承認していないため、変更は公開されていません。",
|
||||
"mail_template_approval_2": "レビュアーの過半数がその変更を承認しなかったため、その変更は公開されませんでした。",
|
||||
"mail_template_approval_3": "全会一致の承認が得られなかったため、変更は公開されませんでした。",
|
||||
"mail_template_approval_4": "レビュアーが変更を承認したため、あなたの変更は公開されました。",
|
||||
"mail_template_approval_5": "あなたの変更は、レビュアーの過半数がその変更を承認したため、公開されました。",
|
||||
"mail_template_approval_6": "あなたの変更は全会一致で承認され、公開されました。",
|
||||
"mail_template_approval_7": "あなたの変更はまだレビュー中であり、他のレビュアーがその変更を承認する必要があります。",
|
||||
"mail_template_approval_8": "あなたの変更はまだレビュー中であり、大多数のレビュアーがその変更を承認する必要があります。",
|
||||
"mail_template_approval_9": "あなたの変更はまだレビュー中で、全会一致の承認が必要です。",
|
||||
"mail_template_review_outcome": "{1} はあなたのドキュメント {2} の変更をレビューし、{3} とマークされました。{4}",
|
||||
"mail_template_action_read": "2}までにドキュメント{1}をお読みください。",
|
||||
"mail_template_action_feedback": "2} までにドキュメント {1} に対するフィードバックをお願いします。",
|
||||
"mail_template_action_contribute": "2}までにドキュメント{1}にコンテンツを投稿してください。",
|
||||
"mail_template_publish_request": "{1}はドキュメントの公開を要求しました。",
|
||||
"mail_template_action_assigned": "{1}はあなたにドキュメントアクションを割り当てました",
|
||||
"mail_template_action_done": "{1}はあなたのドキュメントアクションを完了しました",
|
||||
"mail_template_action_read_done": "{1}は{2}のドキュメントを読みました(期限は{3})。",
|
||||
"mail_template_action_feedback_done": "{1} が {2} のドキュメントにフィードバックを提供しました (期限は {3} です)",
|
||||
"mail_template_action_contribute_done": "{1} が {2} のドキュメントにコンテンツを提供しました (期限 {3})",
|
||||
"mail_template_share_doc": "{1} はドキュメントを共有しました",
|
||||
"mail_template_share_viewed": "{1} は閲覧されました",
|
||||
"mail_template_feedback_received": "{1} は {2} に対するフィードバックを送信しました。"
|
||||
}
|
|
@ -6,21 +6,5 @@
|
|||
"theme_color": "#280A42",
|
||||
"description": "Organized documents",
|
||||
"start_url": "/?utm_source=homescreen",
|
||||
"icons": [{
|
||||
"src": "assets/img/icon.png",
|
||||
"sizes": "64x64",
|
||||
"type": "image/png"
|
||||
}, {
|
||||
"src": "assets/img/icon.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png"
|
||||
}, {
|
||||
"src": "assets/img/icon.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png"
|
||||
}, {
|
||||
"src": "assets/img/icon.png",
|
||||
"sizes": "1024x1024",
|
||||
"type": "image/png"
|
||||
}]
|
||||
"icons": []
|
||||
}
|
||||
|
|
24435
gui/yarn.lock
24435
gui/yarn.lock
File diff suppressed because it is too large
Load diff
41
vendor/github.com/Azure/go-ntlmssp/SECURITY.md
generated
vendored
Normal file
41
vendor/github.com/Azure/go-ntlmssp/SECURITY.md
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.8 BLOCK -->
|
||||
|
||||
## Security
|
||||
|
||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||
|
||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
|
||||
|
||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
|
||||
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
|
||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
* Full paths of source file(s) related to the manifestation of the issue
|
||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||
* Any special configuration required to reproduce the issue
|
||||
* Step-by-step instructions to reproduce the issue
|
||||
* Proof-of-concept or exploit code (if possible)
|
||||
* Impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly.
|
||||
|
||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
|
||||
|
||||
## Preferred Languages
|
||||
|
||||
We prefer all communications to be in English.
|
||||
|
||||
## Policy
|
||||
|
||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
|
||||
|
||||
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
8
vendor/github.com/Azure/go-ntlmssp/authenticate_message.go
generated
vendored
8
vendor/github.com/Azure/go-ntlmssp/authenticate_message.go
generated
vendored
|
@ -42,7 +42,7 @@ func (m authenicateMessage) MarshalBinary() ([]byte, error) {
|
|||
}
|
||||
|
||||
target, user := toUnicode(m.TargetName), toUnicode(m.UserName)
|
||||
workstation := toUnicode("go-ntlmssp")
|
||||
workstation := toUnicode("")
|
||||
|
||||
ptr := binary.Size(&authenticateMessageFields{})
|
||||
f := authenticateMessageFields{
|
||||
|
@ -82,7 +82,7 @@ func (m authenicateMessage) MarshalBinary() ([]byte, error) {
|
|||
|
||||
//ProcessChallenge crafts an AUTHENTICATE message in response to the CHALLENGE message
|
||||
//that was received from the server
|
||||
func ProcessChallenge(challengeMessageData []byte, user, password string) ([]byte, error) {
|
||||
func ProcessChallenge(challengeMessageData []byte, user, password string, domainNeeded bool) ([]byte, error) {
|
||||
if user == "" && password == "" {
|
||||
return nil, errors.New("Anonymous authentication not supported")
|
||||
}
|
||||
|
@ -98,6 +98,10 @@ func ProcessChallenge(challengeMessageData []byte, user, password string) ([]byt
|
|||
if cm.NegotiateFlags.Has(negotiateFlagNTLMSSPNEGOTIATEKEYEXCH) {
|
||||
return nil, errors.New("Key exchange requested but not supported (NTLMSSP_NEGOTIATE_KEY_EXCH)")
|
||||
}
|
||||
|
||||
if !domainNeeded {
|
||||
cm.TargetName = ""
|
||||
}
|
||||
|
||||
am := authenicateMessage{
|
||||
UserName: user,
|
||||
|
|
45
vendor/github.com/Azure/go-ntlmssp/authheader.go
generated
vendored
45
vendor/github.com/Azure/go-ntlmssp/authheader.go
generated
vendored
|
@ -5,26 +5,55 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
type authheader string
|
||||
type authheader []string
|
||||
|
||||
func (h authheader) IsBasic() bool {
|
||||
return strings.HasPrefix(string(h), "Basic ")
|
||||
for _, s := range h {
|
||||
if strings.HasPrefix(string(s), "Basic ") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (h authheader) Basic() string {
|
||||
for _, s := range h {
|
||||
if strings.HasPrefix(string(s), "Basic ") {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (h authheader) IsNegotiate() bool {
|
||||
return strings.HasPrefix(string(h), "Negotiate")
|
||||
for _, s := range h {
|
||||
if strings.HasPrefix(string(s), "Negotiate") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (h authheader) IsNTLM() bool {
|
||||
return strings.HasPrefix(string(h), "NTLM")
|
||||
for _, s := range h {
|
||||
if strings.HasPrefix(string(s), "NTLM") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (h authheader) GetData() ([]byte, error) {
|
||||
p := strings.Split(string(h), " ")
|
||||
if len(p) < 2 {
|
||||
return nil, nil
|
||||
for _, s := range h {
|
||||
if strings.HasPrefix(string(s), "NTLM") || strings.HasPrefix(string(s), "Negotiate") || strings.HasPrefix(string(s), "Basic ") {
|
||||
p := strings.Split(string(s), " ")
|
||||
if len(p) < 2 {
|
||||
return nil, nil
|
||||
}
|
||||
return base64.StdEncoding.DecodeString(string(p[1]))
|
||||
}
|
||||
}
|
||||
return base64.StdEncoding.DecodeString(string(p[1]))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (h authheader) GetBasicCreds() (username, password string, err error) {
|
||||
|
|
27
vendor/github.com/Azure/go-ntlmssp/negotiator.go
generated
vendored
27
vendor/github.com/Azure/go-ntlmssp/negotiator.go
generated
vendored
|
@ -10,15 +10,22 @@ import (
|
|||
)
|
||||
|
||||
// GetDomain : parse domain name from based on slashes in the input
|
||||
func GetDomain(user string) (string, string) {
|
||||
// Need to check for upn as well
|
||||
func GetDomain(user string) (string, string, bool) {
|
||||
domain := ""
|
||||
domainNeeded := false
|
||||
|
||||
if strings.Contains(user, "\\") {
|
||||
ucomponents := strings.SplitN(user, "\\", 2)
|
||||
domain = ucomponents[0]
|
||||
user = ucomponents[1]
|
||||
domainNeeded = true
|
||||
} else if strings.Contains(user, "@") {
|
||||
domainNeeded = false
|
||||
} else {
|
||||
domainNeeded = true
|
||||
}
|
||||
return user, domain
|
||||
return user, domain, domainNeeded
|
||||
}
|
||||
|
||||
//Negotiator is a http.Roundtripper decorator that automatically
|
||||
|
@ -34,10 +41,11 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
|||
rt = http.DefaultTransport
|
||||
}
|
||||
// If it is not basic auth, just round trip the request as usual
|
||||
reqauth := authheader(req.Header.Get("Authorization"))
|
||||
reqauth := authheader(req.Header.Values("Authorization"))
|
||||
if !reqauth.IsBasic() {
|
||||
return rt.RoundTrip(req)
|
||||
}
|
||||
reqauthBasic := reqauth.Basic()
|
||||
// Save request body
|
||||
body := bytes.Buffer{}
|
||||
if req.Body != nil {
|
||||
|
@ -59,11 +67,10 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
|||
if res.StatusCode != http.StatusUnauthorized {
|
||||
return res, err
|
||||
}
|
||||
|
||||
resauth := authheader(res.Header.Get("Www-Authenticate"))
|
||||
resauth := authheader(res.Header.Values("Www-Authenticate"))
|
||||
if !resauth.IsNegotiate() && !resauth.IsNTLM() {
|
||||
// Unauthorized, Negotiate not requested, let's try with basic auth
|
||||
req.Header.Set("Authorization", string(reqauth))
|
||||
req.Header.Set("Authorization", string(reqauthBasic))
|
||||
io.Copy(ioutil.Discard, res.Body)
|
||||
res.Body.Close()
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
||||
|
@ -75,7 +82,7 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
|||
if res.StatusCode != http.StatusUnauthorized {
|
||||
return res, err
|
||||
}
|
||||
resauth = authheader(res.Header.Get("Www-Authenticate"))
|
||||
resauth = authheader(res.Header.Values("Www-Authenticate"))
|
||||
}
|
||||
|
||||
if resauth.IsNegotiate() || resauth.IsNTLM() {
|
||||
|
@ -91,7 +98,7 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
|||
|
||||
// get domain from username
|
||||
domain := ""
|
||||
u, domain = GetDomain(u)
|
||||
u, domain, domainNeeded := GetDomain(u)
|
||||
|
||||
// send negotiate
|
||||
negotiateMessage, err := NewNegotiateMessage(domain, "")
|
||||
|
@ -112,7 +119,7 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
|||
}
|
||||
|
||||
// receive challenge?
|
||||
resauth = authheader(res.Header.Get("Www-Authenticate"))
|
||||
resauth = authheader(res.Header.Values("Www-Authenticate"))
|
||||
challengeMessage, err := resauth.GetData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -125,7 +132,7 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
|||
res.Body.Close()
|
||||
|
||||
// send authenticate
|
||||
authenticateMessage, err := ProcessChallenge(challengeMessage, u, p)
|
||||
authenticateMessage, err := ProcessChallenge(challengeMessage, u, p, domainNeeded)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
7
vendor/github.com/BurntSushi/toml/.gitignore
generated
vendored
7
vendor/github.com/BurntSushi/toml/.gitignore
generated
vendored
|
@ -1,5 +1,2 @@
|
|||
TAGS
|
||||
tags
|
||||
.*.swp
|
||||
tomlcheck/tomlcheck
|
||||
toml.test
|
||||
/toml.test
|
||||
/toml-test
|
||||
|
|
15
vendor/github.com/BurntSushi/toml/.travis.yml
generated
vendored
15
vendor/github.com/BurntSushi/toml/.travis.yml
generated
vendored
|
@ -1,15 +0,0 @@
|
|||
language: go
|
||||
go:
|
||||
- 1.1
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- tip
|
||||
install:
|
||||
- go install ./...
|
||||
- go get github.com/BurntSushi/toml-test
|
||||
script:
|
||||
- export PATH="$PATH:$HOME/gopath/bin"
|
||||
- make test
|
3
vendor/github.com/BurntSushi/toml/COMPATIBLE
generated
vendored
3
vendor/github.com/BurntSushi/toml/COMPATIBLE
generated
vendored
|
@ -1,3 +0,0 @@
|
|||
Compatible with TOML version
|
||||
[v0.4.0](https://github.com/toml-lang/toml/blob/v0.4.0/versions/en/toml-v0.4.0.md)
|
||||
|
19
vendor/github.com/BurntSushi/toml/Makefile
generated
vendored
19
vendor/github.com/BurntSushi/toml/Makefile
generated
vendored
|
@ -1,19 +0,0 @@
|
|||
install:
|
||||
go install ./...
|
||||
|
||||
test: install
|
||||
go test -v
|
||||
toml-test toml-test-decoder
|
||||
toml-test -encoder toml-test-encoder
|
||||
|
||||
fmt:
|
||||
gofmt -w *.go */*.go
|
||||
colcheck *.go */*.go
|
||||
|
||||
tags:
|
||||
find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS
|
||||
|
||||
push:
|
||||
git push origin master
|
||||
git push github master
|
||||
|
228
vendor/github.com/BurntSushi/toml/README.md
generated
vendored
228
vendor/github.com/BurntSushi/toml/README.md
generated
vendored
|
@ -1,46 +1,26 @@
|
|||
## TOML parser and encoder for Go with reflection
|
||||
|
||||
TOML stands for Tom's Obvious, Minimal Language. This Go package provides a
|
||||
reflection interface similar to Go's standard library `json` and `xml`
|
||||
packages. This package also supports the `encoding.TextUnmarshaler` and
|
||||
`encoding.TextMarshaler` interfaces so that you can define custom data
|
||||
representations. (There is an example of this below.)
|
||||
reflection interface similar to Go's standard library `json` and `xml` packages.
|
||||
|
||||
Spec: https://github.com/toml-lang/toml
|
||||
Compatible with TOML version [v1.0.0](https://toml.io/en/v1.0.0).
|
||||
|
||||
Compatible with TOML version
|
||||
[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md)
|
||||
Documentation: https://godocs.io/github.com/BurntSushi/toml
|
||||
|
||||
Documentation: https://godoc.org/github.com/BurntSushi/toml
|
||||
See the [releases page](https://github.com/BurntSushi/toml/releases) for a
|
||||
changelog; this information is also in the git tag annotations (e.g. `git show
|
||||
v0.4.0`).
|
||||
|
||||
Installation:
|
||||
This library requires Go 1.13 or newer; add it to your go.mod with:
|
||||
|
||||
```bash
|
||||
go get github.com/BurntSushi/toml
|
||||
```
|
||||
% go get github.com/BurntSushi/toml@latest
|
||||
|
||||
Try the toml validator:
|
||||
It also comes with a TOML validator CLI tool:
|
||||
|
||||
```bash
|
||||
go get github.com/BurntSushi/toml/cmd/tomlv
|
||||
tomlv some-toml-file.toml
|
||||
```
|
||||
|
||||
[](https://travis-ci.org/BurntSushi/toml) [](https://godoc.org/github.com/BurntSushi/toml)
|
||||
|
||||
### Testing
|
||||
|
||||
This package passes all tests in
|
||||
[toml-test](https://github.com/BurntSushi/toml-test) for both the decoder
|
||||
and the encoder.
|
||||
% go install github.com/BurntSushi/toml/cmd/tomlv@latest
|
||||
% tomlv some-toml-file.toml
|
||||
|
||||
### Examples
|
||||
|
||||
This package works similarly to how the Go standard library handles `XML`
|
||||
and `JSON`. Namely, data is loaded into Go values via reflection.
|
||||
|
||||
For the simplest example, consider some TOML file as just a list of keys
|
||||
and values:
|
||||
For the simplest example, consider some TOML file as just a list of keys and
|
||||
values:
|
||||
|
||||
```toml
|
||||
Age = 25
|
||||
|
@ -50,29 +30,23 @@ Perfection = [ 6, 28, 496, 8128 ]
|
|||
DOB = 1987-07-05T05:45:00Z
|
||||
```
|
||||
|
||||
Which could be defined in Go as:
|
||||
Which can be decoded with:
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
Age int
|
||||
Cats []string
|
||||
Pi float64
|
||||
Perfection []int
|
||||
DOB time.Time // requires `import time`
|
||||
Age int
|
||||
Cats []string
|
||||
Pi float64
|
||||
Perfection []int
|
||||
DOB time.Time
|
||||
}
|
||||
```
|
||||
|
||||
And then decoded with:
|
||||
|
||||
```go
|
||||
var conf Config
|
||||
if _, err := toml.Decode(tomlData, &conf); err != nil {
|
||||
// handle error
|
||||
}
|
||||
_, err := toml.Decode(tomlData, &conf)
|
||||
```
|
||||
|
||||
You can also use struct tags if your struct field name doesn't map to a TOML
|
||||
key value directly:
|
||||
You can also use struct tags if your struct field name doesn't map to a TOML key
|
||||
value directly:
|
||||
|
||||
```toml
|
||||
some_key_NAME = "wat"
|
||||
|
@ -80,139 +54,67 @@ some_key_NAME = "wat"
|
|||
|
||||
```go
|
||||
type TOML struct {
|
||||
ObscureKey string `toml:"some_key_NAME"`
|
||||
ObscureKey string `toml:"some_key_NAME"`
|
||||
}
|
||||
```
|
||||
|
||||
### Using the `encoding.TextUnmarshaler` interface
|
||||
Beware that like other decoders **only exported fields** are considered when
|
||||
encoding and decoding; private fields are silently ignored.
|
||||
|
||||
Here's an example that automatically parses duration strings into
|
||||
`time.Duration` values:
|
||||
### Using the `Marshaler` and `encoding.TextUnmarshaler` interfaces
|
||||
Here's an example that automatically parses values in a `mail.Address`:
|
||||
|
||||
```toml
|
||||
[[song]]
|
||||
name = "Thunder Road"
|
||||
duration = "4m49s"
|
||||
|
||||
[[song]]
|
||||
name = "Stairway to Heaven"
|
||||
duration = "8m03s"
|
||||
```
|
||||
|
||||
Which can be decoded with:
|
||||
|
||||
```go
|
||||
type song struct {
|
||||
Name string
|
||||
Duration duration
|
||||
}
|
||||
type songs struct {
|
||||
Song []song
|
||||
}
|
||||
var favorites songs
|
||||
if _, err := toml.Decode(blob, &favorites); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, s := range favorites.Song {
|
||||
fmt.Printf("%s (%s)\n", s.Name, s.Duration)
|
||||
}
|
||||
```
|
||||
|
||||
And you'll also need a `duration` type that satisfies the
|
||||
`encoding.TextUnmarshaler` interface:
|
||||
|
||||
```go
|
||||
type duration struct {
|
||||
time.Duration
|
||||
}
|
||||
|
||||
func (d *duration) UnmarshalText(text []byte) error {
|
||||
var err error
|
||||
d.Duration, err = time.ParseDuration(string(text))
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
### More complex usage
|
||||
|
||||
Here's an example of how to load the example from the official spec page:
|
||||
|
||||
```toml
|
||||
# This is a TOML document. Boom.
|
||||
|
||||
title = "TOML Example"
|
||||
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
organization = "GitHub"
|
||||
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
|
||||
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
|
||||
|
||||
[database]
|
||||
server = "192.168.1.1"
|
||||
ports = [ 8001, 8001, 8002 ]
|
||||
connection_max = 5000
|
||||
enabled = true
|
||||
|
||||
[servers]
|
||||
|
||||
# You can indent as you please. Tabs or spaces. TOML don't care.
|
||||
[servers.alpha]
|
||||
ip = "10.0.0.1"
|
||||
dc = "eqdc10"
|
||||
|
||||
[servers.beta]
|
||||
ip = "10.0.0.2"
|
||||
dc = "eqdc10"
|
||||
|
||||
[clients]
|
||||
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
|
||||
|
||||
# Line breaks are OK when inside arrays
|
||||
hosts = [
|
||||
"alpha",
|
||||
"omega"
|
||||
contacts = [
|
||||
"Donald Duck <donald@duckburg.com>",
|
||||
"Scrooge McDuck <scrooge@duckburg.com>",
|
||||
]
|
||||
```
|
||||
|
||||
And the corresponding Go types are:
|
||||
Can be decoded with:
|
||||
|
||||
```go
|
||||
type tomlConfig struct {
|
||||
Title string
|
||||
Owner ownerInfo
|
||||
DB database `toml:"database"`
|
||||
Servers map[string]server
|
||||
Clients clients
|
||||
// Create address type which satisfies the encoding.TextUnmarshaler interface.
|
||||
type address struct {
|
||||
*mail.Address
|
||||
}
|
||||
|
||||
type ownerInfo struct {
|
||||
Name string
|
||||
Org string `toml:"organization"`
|
||||
Bio string
|
||||
DOB time.Time
|
||||
func (a *address) UnmarshalText(text []byte) error {
|
||||
var err error
|
||||
a.Address, err = mail.ParseAddress(string(text))
|
||||
return err
|
||||
}
|
||||
|
||||
type database struct {
|
||||
Server string
|
||||
Ports []int
|
||||
ConnMax int `toml:"connection_max"`
|
||||
Enabled bool
|
||||
}
|
||||
// Decode it.
|
||||
func decode() {
|
||||
blob := `
|
||||
contacts = [
|
||||
"Donald Duck <donald@duckburg.com>",
|
||||
"Scrooge McDuck <scrooge@duckburg.com>",
|
||||
]
|
||||
`
|
||||
|
||||
type server struct {
|
||||
IP string
|
||||
DC string
|
||||
}
|
||||
var contacts struct {
|
||||
Contacts []address
|
||||
}
|
||||
|
||||
type clients struct {
|
||||
Data [][]interface{}
|
||||
Hosts []string
|
||||
_, err := toml.Decode(blob, &contacts)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, c := range contacts.Contacts {
|
||||
fmt.Printf("%#v\n", c.Address)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// &mail.Address{Name:"Donald Duck", Address:"donald@duckburg.com"}
|
||||
// &mail.Address{Name:"Scrooge McDuck", Address:"scrooge@duckburg.com"}
|
||||
}
|
||||
```
|
||||
|
||||
Note that a case insensitive match will be tried if an exact match can't be
|
||||
found.
|
||||
To target TOML specifically you can implement `UnmarshalTOML` TOML interface in
|
||||
a similar way.
|
||||
|
||||
A working example of the above can be found in `_examples/example.{go,toml}`.
|
||||
### More complex usage
|
||||
See the [`_example/`](/_example) directory for a more complex example.
|
||||
|
|
539
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
539
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
|
@ -1,157 +1,199 @@
|
|||
package toml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func e(format string, args ...interface{}) error {
|
||||
return fmt.Errorf("toml: "+format, args...)
|
||||
}
|
||||
|
||||
// Unmarshaler is the interface implemented by objects that can unmarshal a
|
||||
// TOML description of themselves.
|
||||
type Unmarshaler interface {
|
||||
UnmarshalTOML(interface{}) error
|
||||
}
|
||||
|
||||
// Unmarshal decodes the contents of `p` in TOML format into a pointer `v`.
|
||||
func Unmarshal(p []byte, v interface{}) error {
|
||||
_, err := Decode(string(p), v)
|
||||
// Unmarshal decodes the contents of data in TOML format into a pointer v.
|
||||
//
|
||||
// See [Decoder] for a description of the decoding process.
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
_, err := NewDecoder(bytes.NewReader(data)).Decode(v)
|
||||
return err
|
||||
}
|
||||
|
||||
// Decode the TOML data in to the pointer v.
|
||||
//
|
||||
// See [Decoder] for a description of the decoding process.
|
||||
func Decode(data string, v interface{}) (MetaData, error) {
|
||||
return NewDecoder(strings.NewReader(data)).Decode(v)
|
||||
}
|
||||
|
||||
// DecodeFile reads the contents of a file and decodes it with [Decode].
|
||||
func DecodeFile(path string, v interface{}) (MetaData, error) {
|
||||
fp, err := os.Open(path)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
defer fp.Close()
|
||||
return NewDecoder(fp).Decode(v)
|
||||
}
|
||||
|
||||
// Primitive is a TOML value that hasn't been decoded into a Go value.
|
||||
// When using the various `Decode*` functions, the type `Primitive` may
|
||||
// be given to any value, and its decoding will be delayed.
|
||||
//
|
||||
// A `Primitive` value can be decoded using the `PrimitiveDecode` function.
|
||||
// This type can be used for any value, which will cause decoding to be delayed.
|
||||
// You can use [PrimitiveDecode] to "manually" decode these values.
|
||||
//
|
||||
// The underlying representation of a `Primitive` value is subject to change.
|
||||
// Do not rely on it.
|
||||
// NOTE: The underlying representation of a `Primitive` value is subject to
|
||||
// change. Do not rely on it.
|
||||
//
|
||||
// N.B. Primitive values are still parsed, so using them will only avoid
|
||||
// the overhead of reflection. They can be useful when you don't know the
|
||||
// exact type of TOML data until run time.
|
||||
// NOTE: Primitive values are still parsed, so using them will only avoid the
|
||||
// overhead of reflection. They can be useful when you don't know the exact type
|
||||
// of TOML data until runtime.
|
||||
type Primitive struct {
|
||||
undecoded interface{}
|
||||
context Key
|
||||
}
|
||||
|
||||
// DEPRECATED!
|
||||
// The significand precision for float32 and float64 is 24 and 53 bits; this is
|
||||
// the range a natural number can be stored in a float without loss of data.
|
||||
const (
|
||||
maxSafeFloat32Int = 16777215 // 2^24-1
|
||||
maxSafeFloat64Int = int64(9007199254740991) // 2^53-1
|
||||
)
|
||||
|
||||
// Decoder decodes TOML data.
|
||||
//
|
||||
// Use MetaData.PrimitiveDecode instead.
|
||||
func PrimitiveDecode(primValue Primitive, v interface{}) error {
|
||||
md := MetaData{decoded: make(map[string]bool)}
|
||||
return md.unify(primValue.undecoded, rvalue(v))
|
||||
// TOML tables correspond to Go structs or maps; they can be used
|
||||
// interchangeably, but structs offer better type safety.
|
||||
//
|
||||
// TOML table arrays correspond to either a slice of structs or a slice of maps.
|
||||
//
|
||||
// TOML datetimes correspond to [time.Time]. Local datetimes are parsed in the
|
||||
// local timezone.
|
||||
//
|
||||
// [time.Duration] types are treated as nanoseconds if the TOML value is an
|
||||
// integer, or they're parsed with time.ParseDuration() if they're strings.
|
||||
//
|
||||
// All other TOML types (float, string, int, bool and array) correspond to the
|
||||
// obvious Go types.
|
||||
//
|
||||
// An exception to the above rules is if a type implements the TextUnmarshaler
|
||||
// interface, in which case any primitive TOML value (floats, strings, integers,
|
||||
// booleans, datetimes) will be converted to a []byte and given to the value's
|
||||
// UnmarshalText method. See the Unmarshaler example for a demonstration with
|
||||
// email addresses.
|
||||
//
|
||||
// # Key mapping
|
||||
//
|
||||
// TOML keys can map to either keys in a Go map or field names in a Go struct.
|
||||
// The special `toml` struct tag can be used to map TOML keys to struct fields
|
||||
// that don't match the key name exactly (see the example). A case insensitive
|
||||
// match to struct names will be tried if an exact match can't be found.
|
||||
//
|
||||
// The mapping between TOML values and Go values is loose. That is, there may
|
||||
// exist TOML values that cannot be placed into your representation, and there
|
||||
// may be parts of your representation that do not correspond to TOML values.
|
||||
// This loose mapping can be made stricter by using the IsDefined and/or
|
||||
// Undecoded methods on the MetaData returned.
|
||||
//
|
||||
// This decoder does not handle cyclic types. Decode will not terminate if a
|
||||
// cyclic type is passed.
|
||||
type Decoder struct {
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
// PrimitiveDecode is just like the other `Decode*` functions, except it
|
||||
// decodes a TOML value that has already been parsed. Valid primitive values
|
||||
// can *only* be obtained from values filled by the decoder functions,
|
||||
// including this method. (i.e., `v` may contain more `Primitive`
|
||||
// values.)
|
||||
// NewDecoder creates a new Decoder.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
return &Decoder{r: r}
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalToml = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
|
||||
unmarshalText = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
||||
primitiveType = reflect.TypeOf((*Primitive)(nil)).Elem()
|
||||
)
|
||||
|
||||
// Decode TOML data in to the pointer `v`.
|
||||
func (dec *Decoder) Decode(v interface{}) (MetaData, error) {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Ptr {
|
||||
s := "%q"
|
||||
if reflect.TypeOf(v) == nil {
|
||||
s = "%v"
|
||||
}
|
||||
|
||||
return MetaData{}, fmt.Errorf("toml: cannot decode to non-pointer "+s, reflect.TypeOf(v))
|
||||
}
|
||||
if rv.IsNil() {
|
||||
return MetaData{}, fmt.Errorf("toml: cannot decode to nil value of %q", reflect.TypeOf(v))
|
||||
}
|
||||
|
||||
// Check if this is a supported type: struct, map, interface{}, or something
|
||||
// that implements UnmarshalTOML or UnmarshalText.
|
||||
rv = indirect(rv)
|
||||
rt := rv.Type()
|
||||
if rv.Kind() != reflect.Struct && rv.Kind() != reflect.Map &&
|
||||
!(rv.Kind() == reflect.Interface && rv.NumMethod() == 0) &&
|
||||
!rt.Implements(unmarshalToml) && !rt.Implements(unmarshalText) {
|
||||
return MetaData{}, fmt.Errorf("toml: cannot decode to type %s", rt)
|
||||
}
|
||||
|
||||
// TODO: parser should read from io.Reader? Or at the very least, make it
|
||||
// read from []byte rather than string
|
||||
data, err := ioutil.ReadAll(dec.r)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
|
||||
p, err := parse(string(data))
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
|
||||
md := MetaData{
|
||||
mapping: p.mapping,
|
||||
keyInfo: p.keyInfo,
|
||||
keys: p.ordered,
|
||||
decoded: make(map[string]struct{}, len(p.ordered)),
|
||||
context: nil,
|
||||
data: data,
|
||||
}
|
||||
return md, md.unify(p.mapping, rv)
|
||||
}
|
||||
|
||||
// PrimitiveDecode is just like the other Decode* functions, except it decodes a
|
||||
// TOML value that has already been parsed. Valid primitive values can *only* be
|
||||
// obtained from values filled by the decoder functions, including this method.
|
||||
// (i.e., v may contain more [Primitive] values.)
|
||||
//
|
||||
// Meta data for primitive values is included in the meta data returned by
|
||||
// the `Decode*` functions with one exception: keys returned by the Undecoded
|
||||
// method will only reflect keys that were decoded. Namely, any keys hidden
|
||||
// behind a Primitive will be considered undecoded. Executing this method will
|
||||
// update the undecoded keys in the meta data. (See the example.)
|
||||
// Meta data for primitive values is included in the meta data returned by the
|
||||
// Decode* functions with one exception: keys returned by the Undecoded method
|
||||
// will only reflect keys that were decoded. Namely, any keys hidden behind a
|
||||
// Primitive will be considered undecoded. Executing this method will update the
|
||||
// undecoded keys in the meta data. (See the example.)
|
||||
func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
|
||||
md.context = primValue.context
|
||||
defer func() { md.context = nil }()
|
||||
return md.unify(primValue.undecoded, rvalue(v))
|
||||
}
|
||||
|
||||
// Decode will decode the contents of `data` in TOML format into a pointer
|
||||
// `v`.
|
||||
//
|
||||
// TOML hashes correspond to Go structs or maps. (Dealer's choice. They can be
|
||||
// used interchangeably.)
|
||||
//
|
||||
// TOML arrays of tables correspond to either a slice of structs or a slice
|
||||
// of maps.
|
||||
//
|
||||
// TOML datetimes correspond to Go `time.Time` values.
|
||||
//
|
||||
// All other TOML types (float, string, int, bool and array) correspond
|
||||
// to the obvious Go types.
|
||||
//
|
||||
// An exception to the above rules is if a type implements the
|
||||
// encoding.TextUnmarshaler interface. In this case, any primitive TOML value
|
||||
// (floats, strings, integers, booleans and datetimes) will be converted to
|
||||
// a byte string and given to the value's UnmarshalText method. See the
|
||||
// Unmarshaler example for a demonstration with time duration strings.
|
||||
//
|
||||
// Key mapping
|
||||
//
|
||||
// TOML keys can map to either keys in a Go map or field names in a Go
|
||||
// struct. The special `toml` struct tag may be used to map TOML keys to
|
||||
// struct fields that don't match the key name exactly. (See the example.)
|
||||
// A case insensitive match to struct names will be tried if an exact match
|
||||
// can't be found.
|
||||
//
|
||||
// The mapping between TOML values and Go values is loose. That is, there
|
||||
// may exist TOML values that cannot be placed into your representation, and
|
||||
// there may be parts of your representation that do not correspond to
|
||||
// TOML values. This loose mapping can be made stricter by using the IsDefined
|
||||
// and/or Undecoded methods on the MetaData returned.
|
||||
//
|
||||
// This decoder will not handle cyclic types. If a cyclic type is passed,
|
||||
// `Decode` will not terminate.
|
||||
func Decode(data string, v interface{}) (MetaData, error) {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Ptr {
|
||||
return MetaData{}, e("Decode of non-pointer %s", reflect.TypeOf(v))
|
||||
}
|
||||
if rv.IsNil() {
|
||||
return MetaData{}, e("Decode of nil %s", reflect.TypeOf(v))
|
||||
}
|
||||
p, err := parse(data)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
md := MetaData{
|
||||
p.mapping, p.types, p.ordered,
|
||||
make(map[string]bool, len(p.ordered)), nil,
|
||||
}
|
||||
return md, md.unify(p.mapping, indirect(rv))
|
||||
}
|
||||
|
||||
// DecodeFile is just like Decode, except it will automatically read the
|
||||
// contents of the file at `fpath` and decode it for you.
|
||||
func DecodeFile(fpath string, v interface{}) (MetaData, error) {
|
||||
bs, err := ioutil.ReadFile(fpath)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
return Decode(string(bs), v)
|
||||
}
|
||||
|
||||
// DecodeReader is just like Decode, except it will consume all bytes
|
||||
// from the reader and decode it for you.
|
||||
func DecodeReader(r io.Reader, v interface{}) (MetaData, error) {
|
||||
bs, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
return Decode(string(bs), v)
|
||||
}
|
||||
|
||||
// unify performs a sort of type unification based on the structure of `rv`,
|
||||
// which is the client representation.
|
||||
//
|
||||
// Any type mismatch produces an error. Finding a type that we don't know
|
||||
// how to handle produces an unsupported type error.
|
||||
func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
|
||||
|
||||
// Special case. Look for a `Primitive` value.
|
||||
if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() {
|
||||
// TODO: #76 would make this superfluous after implemented.
|
||||
if rv.Type() == primitiveType {
|
||||
// Save the undecoded data and the key context into the primitive
|
||||
// value.
|
||||
context := make(Key, len(md.context))
|
||||
|
@ -163,36 +205,24 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Special case. Unmarshaler Interface support.
|
||||
if rv.CanAddr() {
|
||||
if v, ok := rv.Addr().Interface().(Unmarshaler); ok {
|
||||
return v.UnmarshalTOML(data)
|
||||
}
|
||||
rvi := rv.Interface()
|
||||
if v, ok := rvi.(Unmarshaler); ok {
|
||||
return v.UnmarshalTOML(data)
|
||||
}
|
||||
|
||||
// Special case. Handle time.Time values specifically.
|
||||
// TODO: Remove this code when we decide to drop support for Go 1.1.
|
||||
// This isn't necessary in Go 1.2 because time.Time satisfies the encoding
|
||||
// interfaces.
|
||||
if rv.Type().AssignableTo(rvalue(time.Time{}).Type()) {
|
||||
return md.unifyDatetime(data, rv)
|
||||
}
|
||||
|
||||
// Special case. Look for a value satisfying the TextUnmarshaler interface.
|
||||
if v, ok := rv.Interface().(TextUnmarshaler); ok {
|
||||
if v, ok := rvi.(encoding.TextUnmarshaler); ok {
|
||||
return md.unifyText(data, v)
|
||||
}
|
||||
// BUG(burntsushi)
|
||||
|
||||
// TODO:
|
||||
// The behavior here is incorrect whenever a Go type satisfies the
|
||||
// encoding.TextUnmarshaler interface but also corresponds to a TOML
|
||||
// hash or array. In particular, the unmarshaler should only be applied
|
||||
// to primitive TOML values. But at this point, it will be applied to
|
||||
// all kinds of values and produce an incorrect error whenever those values
|
||||
// are hashes or arrays (including arrays of tables).
|
||||
// encoding.TextUnmarshaler interface but also corresponds to a TOML hash or
|
||||
// array. In particular, the unmarshaler should only be applied to primitive
|
||||
// TOML values. But at this point, it will be applied to all kinds of values
|
||||
// and produce an incorrect error whenever those values are hashes or arrays
|
||||
// (including arrays of tables).
|
||||
|
||||
k := rv.Kind()
|
||||
|
||||
// laziness
|
||||
if k >= reflect.Int && k <= reflect.Uint64 {
|
||||
return md.unifyInt(data, rv)
|
||||
}
|
||||
|
@ -218,17 +248,14 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
|
|||
case reflect.Bool:
|
||||
return md.unifyBool(data, rv)
|
||||
case reflect.Interface:
|
||||
// we only support empty interfaces.
|
||||
if rv.NumMethod() > 0 {
|
||||
return e("unsupported type %s", rv.Type())
|
||||
if rv.NumMethod() > 0 { /// Only empty interfaces are supported.
|
||||
return md.e("unsupported type %s", rv.Type())
|
||||
}
|
||||
return md.unifyAnything(data, rv)
|
||||
case reflect.Float32:
|
||||
fallthrough
|
||||
case reflect.Float64:
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return md.unifyFloat64(data, rv)
|
||||
}
|
||||
return e("unsupported type %s", rv.Kind())
|
||||
return md.e("unsupported type %s", rv.Kind())
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
|
||||
|
@ -237,7 +264,7 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
|
|||
if mapping == nil {
|
||||
return nil
|
||||
}
|
||||
return e("type mismatch for %s: expected table but found %T",
|
||||
return md.e("type mismatch for %s: expected table but found %T",
|
||||
rv.Type().String(), mapping)
|
||||
}
|
||||
|
||||
|
@ -259,17 +286,18 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
|
|||
for _, i := range f.index {
|
||||
subv = indirect(subv.Field(i))
|
||||
}
|
||||
|
||||
if isUnifiable(subv) {
|
||||
md.decoded[md.context.add(key).String()] = true
|
||||
md.decoded[md.context.add(key).String()] = struct{}{}
|
||||
md.context = append(md.context, key)
|
||||
if err := md.unify(datum, subv); err != nil {
|
||||
|
||||
err := md.unify(datum, subv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
md.context = md.context[0 : len(md.context)-1]
|
||||
} else if f.name != "" {
|
||||
// Bad user! No soup for you!
|
||||
return e("cannot write unexported field %s.%s",
|
||||
rv.Type().String(), f.name)
|
||||
return md.e("cannot write unexported field %s.%s", rv.Type().String(), f.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -277,28 +305,43 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
|
|||
}
|
||||
|
||||
func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error {
|
||||
keyType := rv.Type().Key().Kind()
|
||||
if keyType != reflect.String && keyType != reflect.Interface {
|
||||
return fmt.Errorf("toml: cannot decode to a map with non-string key type (%s in %q)",
|
||||
keyType, rv.Type())
|
||||
}
|
||||
|
||||
tmap, ok := mapping.(map[string]interface{})
|
||||
if !ok {
|
||||
if tmap == nil {
|
||||
return nil
|
||||
}
|
||||
return badtype("map", mapping)
|
||||
return md.badtype("map", mapping)
|
||||
}
|
||||
if rv.IsNil() {
|
||||
rv.Set(reflect.MakeMap(rv.Type()))
|
||||
}
|
||||
for k, v := range tmap {
|
||||
md.decoded[md.context.add(k).String()] = true
|
||||
md.decoded[md.context.add(k).String()] = struct{}{}
|
||||
md.context = append(md.context, k)
|
||||
|
||||
rvkey := indirect(reflect.New(rv.Type().Key()))
|
||||
rvval := reflect.Indirect(reflect.New(rv.Type().Elem()))
|
||||
if err := md.unify(v, rvval); err != nil {
|
||||
|
||||
err := md.unify(v, indirect(rvval))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
md.context = md.context[0 : len(md.context)-1]
|
||||
|
||||
rvkey.SetString(k)
|
||||
rvkey := indirect(reflect.New(rv.Type().Key()))
|
||||
|
||||
switch keyType {
|
||||
case reflect.Interface:
|
||||
rvkey.Set(reflect.ValueOf(k))
|
||||
case reflect.String:
|
||||
rvkey.SetString(k)
|
||||
}
|
||||
|
||||
rv.SetMapIndex(rvkey, rvval)
|
||||
}
|
||||
return nil
|
||||
|
@ -310,12 +353,10 @@ func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error {
|
|||
if !datav.IsValid() {
|
||||
return nil
|
||||
}
|
||||
return badtype("slice", data)
|
||||
return md.badtype("slice", data)
|
||||
}
|
||||
sliceLen := datav.Len()
|
||||
if sliceLen != rv.Len() {
|
||||
return e("expected array length %d; got TOML array of length %d",
|
||||
rv.Len(), sliceLen)
|
||||
if l := datav.Len(); l != rv.Len() {
|
||||
return md.e("expected array length %d; got TOML array of length %d", rv.Len(), l)
|
||||
}
|
||||
return md.unifySliceArray(datav, rv)
|
||||
}
|
||||
|
@ -326,7 +367,7 @@ func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
|
|||
if !datav.IsValid() {
|
||||
return nil
|
||||
}
|
||||
return badtype("slice", data)
|
||||
return md.badtype("slice", data)
|
||||
}
|
||||
n := datav.Len()
|
||||
if rv.IsNil() || rv.Cap() < n {
|
||||
|
@ -337,37 +378,45 @@ func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
|
|||
}
|
||||
|
||||
func (md *MetaData) unifySliceArray(data, rv reflect.Value) error {
|
||||
sliceLen := data.Len()
|
||||
for i := 0; i < sliceLen; i++ {
|
||||
v := data.Index(i).Interface()
|
||||
sliceval := indirect(rv.Index(i))
|
||||
if err := md.unify(v, sliceval); err != nil {
|
||||
l := data.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
err := md.unify(data.Index(i).Interface(), indirect(rv.Index(i)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyDatetime(data interface{}, rv reflect.Value) error {
|
||||
if _, ok := data.(time.Time); ok {
|
||||
rv.Set(reflect.ValueOf(data))
|
||||
func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error {
|
||||
_, ok := rv.Interface().(json.Number)
|
||||
if ok {
|
||||
if i, ok := data.(int64); ok {
|
||||
rv.SetString(strconv.FormatInt(i, 10))
|
||||
} else if f, ok := data.(float64); ok {
|
||||
rv.SetString(strconv.FormatFloat(f, 'f', -1, 64))
|
||||
} else {
|
||||
return md.badtype("string", data)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return badtype("time.Time", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error {
|
||||
if s, ok := data.(string); ok {
|
||||
rv.SetString(s)
|
||||
return nil
|
||||
}
|
||||
return badtype("string", data)
|
||||
return md.badtype("string", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error {
|
||||
rvk := rv.Kind()
|
||||
|
||||
if num, ok := data.(float64); ok {
|
||||
switch rv.Kind() {
|
||||
switch rvk {
|
||||
case reflect.Float32:
|
||||
if num < -math.MaxFloat32 || num > math.MaxFloat32 {
|
||||
return md.parseErr(errParseRange{i: num, size: rvk.String()})
|
||||
}
|
||||
fallthrough
|
||||
case reflect.Float64:
|
||||
rv.SetFloat(num)
|
||||
|
@ -376,54 +425,60 @@ func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
return badtype("float", data)
|
||||
|
||||
if num, ok := data.(int64); ok {
|
||||
if (rvk == reflect.Float32 && (num < -maxSafeFloat32Int || num > maxSafeFloat32Int)) ||
|
||||
(rvk == reflect.Float64 && (num < -maxSafeFloat64Int || num > maxSafeFloat64Int)) {
|
||||
return md.parseErr(errParseRange{i: num, size: rvk.String()})
|
||||
}
|
||||
rv.SetFloat(float64(num))
|
||||
return nil
|
||||
}
|
||||
|
||||
return md.badtype("float", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error {
|
||||
if num, ok := data.(int64); ok {
|
||||
if rv.Kind() >= reflect.Int && rv.Kind() <= reflect.Int64 {
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int64:
|
||||
// No bounds checking necessary.
|
||||
case reflect.Int8:
|
||||
if num < math.MinInt8 || num > math.MaxInt8 {
|
||||
return e("value %d is out of range for int8", num)
|
||||
}
|
||||
case reflect.Int16:
|
||||
if num < math.MinInt16 || num > math.MaxInt16 {
|
||||
return e("value %d is out of range for int16", num)
|
||||
}
|
||||
case reflect.Int32:
|
||||
if num < math.MinInt32 || num > math.MaxInt32 {
|
||||
return e("value %d is out of range for int32", num)
|
||||
}
|
||||
_, ok := rv.Interface().(time.Duration)
|
||||
if ok {
|
||||
// Parse as string duration, and fall back to regular integer parsing
|
||||
// (as nanosecond) if this is not a string.
|
||||
if s, ok := data.(string); ok {
|
||||
dur, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
return md.parseErr(errParseDuration{s})
|
||||
}
|
||||
rv.SetInt(num)
|
||||
} else if rv.Kind() >= reflect.Uint && rv.Kind() <= reflect.Uint64 {
|
||||
unum := uint64(num)
|
||||
switch rv.Kind() {
|
||||
case reflect.Uint, reflect.Uint64:
|
||||
// No bounds checking necessary.
|
||||
case reflect.Uint8:
|
||||
if num < 0 || unum > math.MaxUint8 {
|
||||
return e("value %d is out of range for uint8", num)
|
||||
}
|
||||
case reflect.Uint16:
|
||||
if num < 0 || unum > math.MaxUint16 {
|
||||
return e("value %d is out of range for uint16", num)
|
||||
}
|
||||
case reflect.Uint32:
|
||||
if num < 0 || unum > math.MaxUint32 {
|
||||
return e("value %d is out of range for uint32", num)
|
||||
}
|
||||
}
|
||||
rv.SetUint(unum)
|
||||
} else {
|
||||
panic("unreachable")
|
||||
rv.SetInt(int64(dur))
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return badtype("integer", data)
|
||||
|
||||
num, ok := data.(int64)
|
||||
if !ok {
|
||||
return md.badtype("integer", data)
|
||||
}
|
||||
|
||||
rvk := rv.Kind()
|
||||
switch {
|
||||
case rvk >= reflect.Int && rvk <= reflect.Int64:
|
||||
if (rvk == reflect.Int8 && (num < math.MinInt8 || num > math.MaxInt8)) ||
|
||||
(rvk == reflect.Int16 && (num < math.MinInt16 || num > math.MaxInt16)) ||
|
||||
(rvk == reflect.Int32 && (num < math.MinInt32 || num > math.MaxInt32)) {
|
||||
return md.parseErr(errParseRange{i: num, size: rvk.String()})
|
||||
}
|
||||
rv.SetInt(num)
|
||||
case rvk >= reflect.Uint && rvk <= reflect.Uint64:
|
||||
unum := uint64(num)
|
||||
if rvk == reflect.Uint8 && (num < 0 || unum > math.MaxUint8) ||
|
||||
rvk == reflect.Uint16 && (num < 0 || unum > math.MaxUint16) ||
|
||||
rvk == reflect.Uint32 && (num < 0 || unum > math.MaxUint32) {
|
||||
return md.parseErr(errParseRange{i: num, size: rvk.String()})
|
||||
}
|
||||
rv.SetUint(unum)
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error {
|
||||
|
@ -431,7 +486,7 @@ func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error {
|
|||
rv.SetBool(b)
|
||||
return nil
|
||||
}
|
||||
return badtype("boolean", data)
|
||||
return md.badtype("boolean", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error {
|
||||
|
@ -439,10 +494,16 @@ func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error {
|
||||
func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) error {
|
||||
var s string
|
||||
switch sdata := data.(type) {
|
||||
case TextMarshaler:
|
||||
case Marshaler:
|
||||
text, err := sdata.MarshalTOML()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s = string(text)
|
||||
case encoding.TextMarshaler:
|
||||
text, err := sdata.MarshalText()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -459,7 +520,7 @@ func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error {
|
|||
case float64:
|
||||
s = fmt.Sprintf("%f", sdata)
|
||||
default:
|
||||
return badtype("primitive (string-like)", data)
|
||||
return md.badtype("primitive (string-like)", data)
|
||||
}
|
||||
if err := v.UnmarshalText([]byte(s)); err != nil {
|
||||
return err
|
||||
|
@ -467,22 +528,54 @@ func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) badtype(dst string, data interface{}) error {
|
||||
return md.e("incompatible types: TOML value has type %T; destination has type %s", data, dst)
|
||||
}
|
||||
|
||||
func (md *MetaData) parseErr(err error) error {
|
||||
k := md.context.String()
|
||||
return ParseError{
|
||||
LastKey: k,
|
||||
Position: md.keyInfo[k].pos,
|
||||
Line: md.keyInfo[k].pos.Line,
|
||||
err: err,
|
||||
input: string(md.data),
|
||||
}
|
||||
}
|
||||
|
||||
func (md *MetaData) e(format string, args ...interface{}) error {
|
||||
f := "toml: "
|
||||
if len(md.context) > 0 {
|
||||
f = fmt.Sprintf("toml: (last key %q): ", md.context)
|
||||
p := md.keyInfo[md.context.String()].pos
|
||||
if p.Line > 0 {
|
||||
f = fmt.Sprintf("toml: line %d (last key %q): ", p.Line, md.context)
|
||||
}
|
||||
}
|
||||
return fmt.Errorf(f+format, args...)
|
||||
}
|
||||
|
||||
// rvalue returns a reflect.Value of `v`. All pointers are resolved.
|
||||
func rvalue(v interface{}) reflect.Value {
|
||||
return indirect(reflect.ValueOf(v))
|
||||
}
|
||||
|
||||
// indirect returns the value pointed to by a pointer.
|
||||
// Pointers are followed until the value is not a pointer.
|
||||
// New values are allocated for each nil pointer.
|
||||
//
|
||||
// An exception to this rule is if the value satisfies an interface of
|
||||
// interest to us (like encoding.TextUnmarshaler).
|
||||
// Pointers are followed until the value is not a pointer. New values are
|
||||
// allocated for each nil pointer.
|
||||
//
|
||||
// An exception to this rule is if the value satisfies an interface of interest
|
||||
// to us (like encoding.TextUnmarshaler).
|
||||
func indirect(v reflect.Value) reflect.Value {
|
||||
if v.Kind() != reflect.Ptr {
|
||||
if v.CanSet() {
|
||||
pv := v.Addr()
|
||||
if _, ok := pv.Interface().(TextUnmarshaler); ok {
|
||||
pvi := pv.Interface()
|
||||
if _, ok := pvi.(encoding.TextUnmarshaler); ok {
|
||||
return pv
|
||||
}
|
||||
if _, ok := pvi.(Unmarshaler); ok {
|
||||
return pv
|
||||
}
|
||||
}
|
||||
|
@ -498,12 +591,12 @@ func isUnifiable(rv reflect.Value) bool {
|
|||
if rv.CanSet() {
|
||||
return true
|
||||
}
|
||||
if _, ok := rv.Interface().(TextUnmarshaler); ok {
|
||||
rvi := rv.Interface()
|
||||
if _, ok := rvi.(encoding.TextUnmarshaler); ok {
|
||||
return true
|
||||
}
|
||||
if _, ok := rvi.(Unmarshaler); ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func badtype(expected string, data interface{}) error {
|
||||
return e("cannot load TOML value of type %T into a Go %s", data, expected)
|
||||
}
|
||||
|
|
19
vendor/github.com/BurntSushi/toml/decode_go116.go
generated
vendored
Normal file
19
vendor/github.com/BurntSushi/toml/decode_go116.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
package toml
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
)
|
||||
|
||||
// DecodeFS reads the contents of a file from [fs.FS] and decodes it with
|
||||
// [Decode].
|
||||
func DecodeFS(fsys fs.FS, path string, v interface{}) (MetaData, error) {
|
||||
fp, err := fsys.Open(path)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
defer fp.Close()
|
||||
return NewDecoder(fp).Decode(v)
|
||||
}
|
29
vendor/github.com/BurntSushi/toml/deprecated.go
generated
vendored
Normal file
29
vendor/github.com/BurntSushi/toml/deprecated.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
package toml
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"io"
|
||||
)
|
||||
|
||||
// TextMarshaler is an alias for encoding.TextMarshaler.
|
||||
//
|
||||
// Deprecated: use encoding.TextMarshaler
|
||||
type TextMarshaler encoding.TextMarshaler
|
||||
|
||||
// TextUnmarshaler is an alias for encoding.TextUnmarshaler.
|
||||
//
|
||||
// Deprecated: use encoding.TextUnmarshaler
|
||||
type TextUnmarshaler encoding.TextUnmarshaler
|
||||
|
||||
// PrimitiveDecode is an alias for MetaData.PrimitiveDecode().
|
||||
//
|
||||
// Deprecated: use MetaData.PrimitiveDecode.
|
||||
func PrimitiveDecode(primValue Primitive, v interface{}) error {
|
||||
md := MetaData{decoded: make(map[string]struct{})}
|
||||
return md.unify(primValue.undecoded, rvalue(v))
|
||||
}
|
||||
|
||||
// DecodeReader is an alias for NewDecoder(r).Decode(v).
|
||||
//
|
||||
// Deprecated: use NewDecoder(reader).Decode(&value).
|
||||
func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { return NewDecoder(r).Decode(v) }
|
36
vendor/github.com/BurntSushi/toml/doc.go
generated
vendored
36
vendor/github.com/BurntSushi/toml/doc.go
generated
vendored
|
@ -1,27 +1,11 @@
|
|||
/*
|
||||
Package toml provides facilities for decoding and encoding TOML configuration
|
||||
files via reflection. There is also support for delaying decoding with
|
||||
the Primitive type, and querying the set of keys in a TOML document with the
|
||||
MetaData type.
|
||||
|
||||
The specification implemented: https://github.com/toml-lang/toml
|
||||
|
||||
The sub-command github.com/BurntSushi/toml/cmd/tomlv can be used to verify
|
||||
whether a file is a valid TOML document. It can also be used to print the
|
||||
type of each key in a TOML document.
|
||||
|
||||
Testing
|
||||
|
||||
There are two important types of tests used for this package. The first is
|
||||
contained inside '*_test.go' files and uses the standard Go unit testing
|
||||
framework. These tests are primarily devoted to holistically testing the
|
||||
decoder and encoder.
|
||||
|
||||
The second type of testing is used to verify the implementation's adherence
|
||||
to the TOML specification. These tests have been factored into their own
|
||||
project: https://github.com/BurntSushi/toml-test
|
||||
|
||||
The reason the tests are in a separate project is so that they can be used by
|
||||
any implementation of TOML. Namely, it is language agnostic.
|
||||
*/
|
||||
// Package toml implements decoding and encoding of TOML files.
|
||||
//
|
||||
// This package supports TOML v1.0.0, as specified at https://toml.io
|
||||
//
|
||||
// There is also support for delaying decoding with the Primitive type, and
|
||||
// querying the set of keys in a TOML document with the MetaData type.
|
||||
//
|
||||
// The github.com/BurntSushi/toml/cmd/tomlv package implements a TOML validator,
|
||||
// and can be used to verify if TOML document is valid. It can also be used to
|
||||
// print the type of each key.
|
||||
package toml
|
||||
|
|
651
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
651
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
|
@ -2,57 +2,127 @@ package toml
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/BurntSushi/toml/internal"
|
||||
)
|
||||
|
||||
type tomlEncodeError struct{ error }
|
||||
|
||||
var (
|
||||
errArrayMixedElementTypes = errors.New(
|
||||
"toml: cannot encode array with mixed element types")
|
||||
errArrayNilElement = errors.New(
|
||||
"toml: cannot encode array with nil element")
|
||||
errNonString = errors.New(
|
||||
"toml: cannot encode a map with non-string key type")
|
||||
errAnonNonStruct = errors.New(
|
||||
"toml: cannot encode an anonymous field that is not a struct")
|
||||
errArrayNoTable = errors.New(
|
||||
"toml: TOML array element cannot contain a table")
|
||||
errNoKey = errors.New(
|
||||
"toml: top-level values must be Go maps or structs")
|
||||
errAnything = errors.New("") // used in testing
|
||||
errArrayNilElement = errors.New("toml: cannot encode array with nil element")
|
||||
errNonString = errors.New("toml: cannot encode a map with non-string key type")
|
||||
errNoKey = errors.New("toml: top-level values must be Go maps or structs")
|
||||
errAnything = errors.New("") // used in testing
|
||||
)
|
||||
|
||||
var quotedReplacer = strings.NewReplacer(
|
||||
"\t", "\\t",
|
||||
"\n", "\\n",
|
||||
"\r", "\\r",
|
||||
var dblQuotedReplacer = strings.NewReplacer(
|
||||
"\"", "\\\"",
|
||||
"\\", "\\\\",
|
||||
"\x00", `\u0000`,
|
||||
"\x01", `\u0001`,
|
||||
"\x02", `\u0002`,
|
||||
"\x03", `\u0003`,
|
||||
"\x04", `\u0004`,
|
||||
"\x05", `\u0005`,
|
||||
"\x06", `\u0006`,
|
||||
"\x07", `\u0007`,
|
||||
"\b", `\b`,
|
||||
"\t", `\t`,
|
||||
"\n", `\n`,
|
||||
"\x0b", `\u000b`,
|
||||
"\f", `\f`,
|
||||
"\r", `\r`,
|
||||
"\x0e", `\u000e`,
|
||||
"\x0f", `\u000f`,
|
||||
"\x10", `\u0010`,
|
||||
"\x11", `\u0011`,
|
||||
"\x12", `\u0012`,
|
||||
"\x13", `\u0013`,
|
||||
"\x14", `\u0014`,
|
||||
"\x15", `\u0015`,
|
||||
"\x16", `\u0016`,
|
||||
"\x17", `\u0017`,
|
||||
"\x18", `\u0018`,
|
||||
"\x19", `\u0019`,
|
||||
"\x1a", `\u001a`,
|
||||
"\x1b", `\u001b`,
|
||||
"\x1c", `\u001c`,
|
||||
"\x1d", `\u001d`,
|
||||
"\x1e", `\u001e`,
|
||||
"\x1f", `\u001f`,
|
||||
"\x7f", `\u007f`,
|
||||
)
|
||||
|
||||
// Encoder controls the encoding of Go values to a TOML document to some
|
||||
// io.Writer.
|
||||
//
|
||||
// The indentation level can be controlled with the Indent field.
|
||||
type Encoder struct {
|
||||
// A single indentation level. By default it is two spaces.
|
||||
Indent string
|
||||
var (
|
||||
marshalToml = reflect.TypeOf((*Marshaler)(nil)).Elem()
|
||||
marshalText = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
|
||||
)
|
||||
|
||||
// hasWritten is whether we have written any output to w yet.
|
||||
hasWritten bool
|
||||
w *bufio.Writer
|
||||
// Marshaler is the interface implemented by types that can marshal themselves
|
||||
// into valid TOML.
|
||||
type Marshaler interface {
|
||||
MarshalTOML() ([]byte, error)
|
||||
}
|
||||
|
||||
// NewEncoder returns a TOML encoder that encodes Go values to the io.Writer
|
||||
// given. By default, a single indentation level is 2 spaces.
|
||||
// Encoder encodes a Go to a TOML document.
|
||||
//
|
||||
// The mapping between Go values and TOML values should be precisely the same as
|
||||
// for [Decode].
|
||||
//
|
||||
// time.Time is encoded as a RFC 3339 string, and time.Duration as its string
|
||||
// representation.
|
||||
//
|
||||
// The [Marshaler] and [encoding.TextMarshaler] interfaces are supported to
|
||||
// encoding the value as custom TOML.
|
||||
//
|
||||
// If you want to write arbitrary binary data then you will need to use
|
||||
// something like base64 since TOML does not have any binary types.
|
||||
//
|
||||
// When encoding TOML hashes (Go maps or structs), keys without any sub-hashes
|
||||
// are encoded first.
|
||||
//
|
||||
// Go maps will be sorted alphabetically by key for deterministic output.
|
||||
//
|
||||
// The toml struct tag can be used to provide the key name; if omitted the
|
||||
// struct field name will be used. If the "omitempty" option is present the
|
||||
// following value will be skipped:
|
||||
//
|
||||
// - arrays, slices, maps, and string with len of 0
|
||||
// - struct with all zero values
|
||||
// - bool false
|
||||
//
|
||||
// If omitzero is given all int and float types with a value of 0 will be
|
||||
// skipped.
|
||||
//
|
||||
// Encoding Go values without a corresponding TOML representation will return an
|
||||
// error. Examples of this includes maps with non-string keys, slices with nil
|
||||
// elements, embedded non-struct types, and nested slices containing maps or
|
||||
// structs. (e.g. [][]map[string]string is not allowed but []map[string]string
|
||||
// is okay, as is []map[string][]string).
|
||||
//
|
||||
// NOTE: only exported keys are encoded due to the use of reflection. Unexported
|
||||
// keys are silently discarded.
|
||||
type Encoder struct {
|
||||
// String to use for a single indentation level; default is two spaces.
|
||||
Indent string
|
||||
|
||||
w *bufio.Writer
|
||||
hasWritten bool // written any output to w yet?
|
||||
}
|
||||
|
||||
// NewEncoder create a new Encoder.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{
|
||||
w: bufio.NewWriter(w),
|
||||
|
@ -60,32 +130,14 @@ func NewEncoder(w io.Writer) *Encoder {
|
|||
}
|
||||
}
|
||||
|
||||
// Encode writes a TOML representation of the Go value to the underlying
|
||||
// io.Writer. If the value given cannot be encoded to a valid TOML document,
|
||||
// then an error is returned.
|
||||
// Encode writes a TOML representation of the Go value to the [Encoder]'s writer.
|
||||
//
|
||||
// The mapping between Go values and TOML values should be precisely the same
|
||||
// as for the Decode* functions. Similarly, the TextMarshaler interface is
|
||||
// supported by encoding the resulting bytes as strings. (If you want to write
|
||||
// arbitrary binary data then you will need to use something like base64 since
|
||||
// TOML does not have any binary types.)
|
||||
//
|
||||
// When encoding TOML hashes (i.e., Go maps or structs), keys without any
|
||||
// sub-hashes are encoded first.
|
||||
//
|
||||
// If a Go map is encoded, then its keys are sorted alphabetically for
|
||||
// deterministic output. More control over this behavior may be provided if
|
||||
// there is demand for it.
|
||||
//
|
||||
// Encoding Go values without a corresponding TOML representation---like map
|
||||
// types with non-string keys---will cause an error to be returned. Similarly
|
||||
// for mixed arrays/slices, arrays/slices with nil elements, embedded
|
||||
// non-struct types and nested slices containing maps or structs.
|
||||
// (e.g., [][]map[string]string is not allowed but []map[string]string is OK
|
||||
// and so is []map[string][]string.)
|
||||
// An error is returned if the value given cannot be encoded to a valid TOML
|
||||
// document.
|
||||
func (enc *Encoder) Encode(v interface{}) error {
|
||||
rv := eindirect(reflect.ValueOf(v))
|
||||
if err := enc.safeEncode(Key([]string{}), rv); err != nil {
|
||||
err := enc.safeEncode(Key([]string{}), rv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return enc.w.Flush()
|
||||
|
@ -106,13 +158,15 @@ func (enc *Encoder) safeEncode(key Key, rv reflect.Value) (err error) {
|
|||
}
|
||||
|
||||
func (enc *Encoder) encode(key Key, rv reflect.Value) {
|
||||
// Special case. Time needs to be in ISO8601 format.
|
||||
// Special case. If we can marshal the type to text, then we used that.
|
||||
// Basically, this prevents the encoder for handling these types as
|
||||
// generic structs (or whatever the underlying type of a TextMarshaler is).
|
||||
switch rv.Interface().(type) {
|
||||
case time.Time, TextMarshaler:
|
||||
enc.keyEqElement(key, rv)
|
||||
// If we can marshal the type to text, then we use that. This prevents the
|
||||
// encoder for handling these types as generic structs (or whatever the
|
||||
// underlying type of a TextMarshaler is).
|
||||
switch {
|
||||
case isMarshaler(rv):
|
||||
enc.writeKeyValue(key, rv, false)
|
||||
return
|
||||
case rv.Type() == primitiveType: // TODO: #76 would make this superfluous after implemented.
|
||||
enc.encode(key, reflect.ValueOf(rv.Interface().(Primitive).undecoded))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -123,12 +177,12 @@ func (enc *Encoder) encode(key Key, rv reflect.Value) {
|
|||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
|
||||
reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64, reflect.String, reflect.Bool:
|
||||
enc.keyEqElement(key, rv)
|
||||
enc.writeKeyValue(key, rv, false)
|
||||
case reflect.Array, reflect.Slice:
|
||||
if typeEqual(tomlArrayHash, tomlTypeOfGo(rv)) {
|
||||
enc.eArrayOfTables(key, rv)
|
||||
} else {
|
||||
enc.keyEqElement(key, rv)
|
||||
enc.writeKeyValue(key, rv, false)
|
||||
}
|
||||
case reflect.Interface:
|
||||
if rv.IsNil() {
|
||||
|
@ -148,55 +202,114 @@ func (enc *Encoder) encode(key Key, rv reflect.Value) {
|
|||
case reflect.Struct:
|
||||
enc.eTable(key, rv)
|
||||
default:
|
||||
panic(e("unsupported type for key '%s': %s", key, k))
|
||||
encPanic(fmt.Errorf("unsupported type for key '%s': %s", key, k))
|
||||
}
|
||||
}
|
||||
|
||||
// eElement encodes any value that can be an array element (primitives and
|
||||
// arrays).
|
||||
// eElement encodes any value that can be an array element.
|
||||
func (enc *Encoder) eElement(rv reflect.Value) {
|
||||
switch v := rv.Interface().(type) {
|
||||
case time.Time:
|
||||
// Special case time.Time as a primitive. Has to come before
|
||||
// TextMarshaler below because time.Time implements
|
||||
// encoding.TextMarshaler, but we need to always use UTC.
|
||||
enc.wf(v.UTC().Format("2006-01-02T15:04:05Z"))
|
||||
return
|
||||
case TextMarshaler:
|
||||
// Special case. Use text marshaler if it's available for this value.
|
||||
if s, err := v.MarshalText(); err != nil {
|
||||
encPanic(err)
|
||||
} else {
|
||||
enc.writeQuoted(string(s))
|
||||
case time.Time: // Using TextMarshaler adds extra quotes, which we don't want.
|
||||
format := time.RFC3339Nano
|
||||
switch v.Location() {
|
||||
case internal.LocalDatetime:
|
||||
format = "2006-01-02T15:04:05.999999999"
|
||||
case internal.LocalDate:
|
||||
format = "2006-01-02"
|
||||
case internal.LocalTime:
|
||||
format = "15:04:05.999999999"
|
||||
}
|
||||
switch v.Location() {
|
||||
default:
|
||||
enc.wf(v.Format(format))
|
||||
case internal.LocalDatetime, internal.LocalDate, internal.LocalTime:
|
||||
enc.wf(v.In(time.UTC).Format(format))
|
||||
}
|
||||
return
|
||||
case Marshaler:
|
||||
s, err := v.MarshalTOML()
|
||||
if err != nil {
|
||||
encPanic(err)
|
||||
}
|
||||
if s == nil {
|
||||
encPanic(errors.New("MarshalTOML returned nil and no error"))
|
||||
}
|
||||
enc.w.Write(s)
|
||||
return
|
||||
case encoding.TextMarshaler:
|
||||
s, err := v.MarshalText()
|
||||
if err != nil {
|
||||
encPanic(err)
|
||||
}
|
||||
if s == nil {
|
||||
encPanic(errors.New("MarshalText returned nil and no error"))
|
||||
}
|
||||
enc.writeQuoted(string(s))
|
||||
return
|
||||
case time.Duration:
|
||||
enc.writeQuoted(v.String())
|
||||
return
|
||||
case json.Number:
|
||||
n, _ := rv.Interface().(json.Number)
|
||||
|
||||
if n == "" { /// Useful zero value.
|
||||
enc.w.WriteByte('0')
|
||||
return
|
||||
} else if v, err := n.Int64(); err == nil {
|
||||
enc.eElement(reflect.ValueOf(v))
|
||||
return
|
||||
} else if v, err := n.Float64(); err == nil {
|
||||
enc.eElement(reflect.ValueOf(v))
|
||||
return
|
||||
}
|
||||
encPanic(fmt.Errorf("unable to convert %q to int64 or float64", n))
|
||||
}
|
||||
|
||||
switch rv.Kind() {
|
||||
case reflect.Bool:
|
||||
enc.wf(strconv.FormatBool(rv.Bool()))
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
||||
reflect.Int64:
|
||||
enc.wf(strconv.FormatInt(rv.Int(), 10))
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16,
|
||||
reflect.Uint32, reflect.Uint64:
|
||||
enc.wf(strconv.FormatUint(rv.Uint(), 10))
|
||||
case reflect.Float32:
|
||||
enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 32)))
|
||||
case reflect.Float64:
|
||||
enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 64)))
|
||||
case reflect.Array, reflect.Slice:
|
||||
enc.eArrayOrSliceElement(rv)
|
||||
case reflect.Interface:
|
||||
case reflect.Ptr:
|
||||
enc.eElement(rv.Elem())
|
||||
return
|
||||
case reflect.String:
|
||||
enc.writeQuoted(rv.String())
|
||||
case reflect.Bool:
|
||||
enc.wf(strconv.FormatBool(rv.Bool()))
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
enc.wf(strconv.FormatInt(rv.Int(), 10))
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
enc.wf(strconv.FormatUint(rv.Uint(), 10))
|
||||
case reflect.Float32:
|
||||
f := rv.Float()
|
||||
if math.IsNaN(f) {
|
||||
enc.wf("nan")
|
||||
} else if math.IsInf(f, 0) {
|
||||
enc.wf("%cinf", map[bool]byte{true: '-', false: '+'}[math.Signbit(f)])
|
||||
} else {
|
||||
enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 32)))
|
||||
}
|
||||
case reflect.Float64:
|
||||
f := rv.Float()
|
||||
if math.IsNaN(f) {
|
||||
enc.wf("nan")
|
||||
} else if math.IsInf(f, 0) {
|
||||
enc.wf("%cinf", map[bool]byte{true: '-', false: '+'}[math.Signbit(f)])
|
||||
} else {
|
||||
enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 64)))
|
||||
}
|
||||
case reflect.Array, reflect.Slice:
|
||||
enc.eArrayOrSliceElement(rv)
|
||||
case reflect.Struct:
|
||||
enc.eStruct(nil, rv, true)
|
||||
case reflect.Map:
|
||||
enc.eMap(nil, rv, true)
|
||||
case reflect.Interface:
|
||||
enc.eElement(rv.Elem())
|
||||
default:
|
||||
panic(e("unexpected primitive type: %s", rv.Kind()))
|
||||
encPanic(fmt.Errorf("unexpected type: %T", rv.Interface()))
|
||||
}
|
||||
}
|
||||
|
||||
// By the TOML spec, all floats must have a decimal with at least one
|
||||
// number on either side.
|
||||
// By the TOML spec, all floats must have a decimal with at least one number on
|
||||
// either side.
|
||||
func floatAddDecimal(fstr string) string {
|
||||
if !strings.Contains(fstr, ".") {
|
||||
return fstr + ".0"
|
||||
|
@ -205,14 +318,14 @@ func floatAddDecimal(fstr string) string {
|
|||
}
|
||||
|
||||
func (enc *Encoder) writeQuoted(s string) {
|
||||
enc.wf("\"%s\"", quotedReplacer.Replace(s))
|
||||
enc.wf("\"%s\"", dblQuotedReplacer.Replace(s))
|
||||
}
|
||||
|
||||
func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) {
|
||||
length := rv.Len()
|
||||
enc.wf("[")
|
||||
for i := 0; i < length; i++ {
|
||||
elem := rv.Index(i)
|
||||
elem := eindirect(rv.Index(i))
|
||||
enc.eElement(elem)
|
||||
if i != length-1 {
|
||||
enc.wf(", ")
|
||||
|
@ -226,44 +339,43 @@ func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) {
|
|||
encPanic(errNoKey)
|
||||
}
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
trv := rv.Index(i)
|
||||
trv := eindirect(rv.Index(i))
|
||||
if isNil(trv) {
|
||||
continue
|
||||
}
|
||||
panicIfInvalidKey(key)
|
||||
enc.newline()
|
||||
enc.wf("%s[[%s]]", enc.indentStr(key), key.maybeQuotedAll())
|
||||
enc.wf("%s[[%s]]", enc.indentStr(key), key)
|
||||
enc.newline()
|
||||
enc.eMapOrStruct(key, trv)
|
||||
enc.eMapOrStruct(key, trv, false)
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) eTable(key Key, rv reflect.Value) {
|
||||
panicIfInvalidKey(key)
|
||||
if len(key) == 1 {
|
||||
// Output an extra newline between top-level tables.
|
||||
// (The newline isn't written if nothing else has been written though.)
|
||||
enc.newline()
|
||||
}
|
||||
if len(key) > 0 {
|
||||
enc.wf("%s[%s]", enc.indentStr(key), key.maybeQuotedAll())
|
||||
enc.wf("%s[%s]", enc.indentStr(key), key)
|
||||
enc.newline()
|
||||
}
|
||||
enc.eMapOrStruct(key, rv)
|
||||
enc.eMapOrStruct(key, rv, false)
|
||||
}
|
||||
|
||||
func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value) {
|
||||
switch rv := eindirect(rv); rv.Kind() {
|
||||
func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value, inline bool) {
|
||||
switch rv.Kind() {
|
||||
case reflect.Map:
|
||||
enc.eMap(key, rv)
|
||||
enc.eMap(key, rv, inline)
|
||||
case reflect.Struct:
|
||||
enc.eStruct(key, rv)
|
||||
enc.eStruct(key, rv, inline)
|
||||
default:
|
||||
// Should never happen?
|
||||
panic("eTable: unhandled reflect.Value Kind: " + rv.Kind().String())
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) eMap(key Key, rv reflect.Value) {
|
||||
func (enc *Encoder) eMap(key Key, rv reflect.Value, inline bool) {
|
||||
rt := rv.Type()
|
||||
if rt.Key().Kind() != reflect.String {
|
||||
encPanic(errNonString)
|
||||
|
@ -274,68 +386,100 @@ func (enc *Encoder) eMap(key Key, rv reflect.Value) {
|
|||
var mapKeysDirect, mapKeysSub []string
|
||||
for _, mapKey := range rv.MapKeys() {
|
||||
k := mapKey.String()
|
||||
if typeIsHash(tomlTypeOfGo(rv.MapIndex(mapKey))) {
|
||||
if typeIsTable(tomlTypeOfGo(eindirect(rv.MapIndex(mapKey)))) {
|
||||
mapKeysSub = append(mapKeysSub, k)
|
||||
} else {
|
||||
mapKeysDirect = append(mapKeysDirect, k)
|
||||
}
|
||||
}
|
||||
|
||||
var writeMapKeys = func(mapKeys []string) {
|
||||
var writeMapKeys = func(mapKeys []string, trailC bool) {
|
||||
sort.Strings(mapKeys)
|
||||
for _, mapKey := range mapKeys {
|
||||
mrv := rv.MapIndex(reflect.ValueOf(mapKey))
|
||||
if isNil(mrv) {
|
||||
// Don't write anything for nil fields.
|
||||
for i, mapKey := range mapKeys {
|
||||
val := eindirect(rv.MapIndex(reflect.ValueOf(mapKey)))
|
||||
if isNil(val) {
|
||||
continue
|
||||
}
|
||||
enc.encode(key.add(mapKey), mrv)
|
||||
|
||||
if inline {
|
||||
enc.writeKeyValue(Key{mapKey}, val, true)
|
||||
if trailC || i != len(mapKeys)-1 {
|
||||
enc.wf(", ")
|
||||
}
|
||||
} else {
|
||||
enc.encode(key.add(mapKey), val)
|
||||
}
|
||||
}
|
||||
}
|
||||
writeMapKeys(mapKeysDirect)
|
||||
writeMapKeys(mapKeysSub)
|
||||
|
||||
if inline {
|
||||
enc.wf("{")
|
||||
}
|
||||
writeMapKeys(mapKeysDirect, len(mapKeysSub) > 0)
|
||||
writeMapKeys(mapKeysSub, false)
|
||||
if inline {
|
||||
enc.wf("}")
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) eStruct(key Key, rv reflect.Value) {
|
||||
const is32Bit = (32 << (^uint(0) >> 63)) == 32
|
||||
|
||||
func pointerTo(t reflect.Type) reflect.Type {
|
||||
if t.Kind() == reflect.Ptr {
|
||||
return pointerTo(t.Elem())
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
||||
// Write keys for fields directly under this key first, because if we write
|
||||
// a field that creates a new table, then all keys under it will be in that
|
||||
// a field that creates a new table then all keys under it will be in that
|
||||
// table (not the one we're writing here).
|
||||
rt := rv.Type()
|
||||
var fieldsDirect, fieldsSub [][]int
|
||||
var addFields func(rt reflect.Type, rv reflect.Value, start []int)
|
||||
//
|
||||
// Fields is a [][]int: for fieldsDirect this always has one entry (the
|
||||
// struct index). For fieldsSub it contains two entries: the parent field
|
||||
// index from tv, and the field indexes for the fields of the sub.
|
||||
var (
|
||||
rt = rv.Type()
|
||||
fieldsDirect, fieldsSub [][]int
|
||||
addFields func(rt reflect.Type, rv reflect.Value, start []int)
|
||||
)
|
||||
addFields = func(rt reflect.Type, rv reflect.Value, start []int) {
|
||||
for i := 0; i < rt.NumField(); i++ {
|
||||
f := rt.Field(i)
|
||||
// skip unexported fields
|
||||
if f.PkgPath != "" && !f.Anonymous {
|
||||
isEmbed := f.Anonymous && pointerTo(f.Type).Kind() == reflect.Struct
|
||||
if f.PkgPath != "" && !isEmbed { /// Skip unexported fields.
|
||||
continue
|
||||
}
|
||||
frv := rv.Field(i)
|
||||
if f.Anonymous {
|
||||
t := f.Type
|
||||
switch t.Kind() {
|
||||
case reflect.Struct:
|
||||
// Treat anonymous struct fields with
|
||||
// tag names as though they are not
|
||||
// anonymous, like encoding/json does.
|
||||
if getOptions(f.Tag).name == "" {
|
||||
addFields(t, frv, f.Index)
|
||||
continue
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if t.Elem().Kind() == reflect.Struct &&
|
||||
getOptions(f.Tag).name == "" {
|
||||
if !frv.IsNil() {
|
||||
addFields(t.Elem(), frv.Elem(), f.Index)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Fall through to the normal field encoding logic below
|
||||
// for non-struct anonymous fields.
|
||||
opts := getOptions(f.Tag)
|
||||
if opts.skip {
|
||||
continue
|
||||
}
|
||||
|
||||
frv := eindirect(rv.Field(i))
|
||||
|
||||
if is32Bit {
|
||||
// Copy so it works correct on 32bit archs; not clear why this
|
||||
// is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4
|
||||
// This also works fine on 64bit, but 32bit archs are somewhat
|
||||
// rare and this is a wee bit faster.
|
||||
copyStart := make([]int, len(start))
|
||||
copy(copyStart, start)
|
||||
start = copyStart
|
||||
}
|
||||
|
||||
// Treat anonymous struct fields with tag names as though they are
|
||||
// not anonymous, like encoding/json does.
|
||||
//
|
||||
// Non-struct anonymous fields use the normal encoding logic.
|
||||
if isEmbed {
|
||||
if getOptions(f.Tag).name == "" && frv.Kind() == reflect.Struct {
|
||||
addFields(frv.Type(), frv, append(start, f.Index...))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if typeIsHash(tomlTypeOfGo(frv)) {
|
||||
if typeIsTable(tomlTypeOfGo(frv)) {
|
||||
fieldsSub = append(fieldsSub, append(start, f.Index...))
|
||||
} else {
|
||||
fieldsDirect = append(fieldsDirect, append(start, f.Index...))
|
||||
|
@ -344,48 +488,81 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value) {
|
|||
}
|
||||
addFields(rt, rv, nil)
|
||||
|
||||
var writeFields = func(fields [][]int) {
|
||||
writeFields := func(fields [][]int) {
|
||||
for _, fieldIndex := range fields {
|
||||
sft := rt.FieldByIndex(fieldIndex)
|
||||
sf := rv.FieldByIndex(fieldIndex)
|
||||
if isNil(sf) {
|
||||
// Don't write anything for nil fields.
|
||||
continue
|
||||
}
|
||||
fieldType := rt.FieldByIndex(fieldIndex)
|
||||
fieldVal := rv.FieldByIndex(fieldIndex)
|
||||
|
||||
opts := getOptions(sft.Tag)
|
||||
opts := getOptions(fieldType.Tag)
|
||||
if opts.skip {
|
||||
continue
|
||||
}
|
||||
keyName := sft.Name
|
||||
if opts.omitempty && isEmpty(fieldVal) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldVal = eindirect(fieldVal)
|
||||
|
||||
if isNil(fieldVal) { /// Don't write anything for nil fields.
|
||||
continue
|
||||
}
|
||||
|
||||
keyName := fieldType.Name
|
||||
if opts.name != "" {
|
||||
keyName = opts.name
|
||||
}
|
||||
if opts.omitempty && isEmpty(sf) {
|
||||
continue
|
||||
}
|
||||
if opts.omitzero && isZero(sf) {
|
||||
|
||||
if opts.omitzero && isZero(fieldVal) {
|
||||
continue
|
||||
}
|
||||
|
||||
enc.encode(key.add(keyName), sf)
|
||||
if inline {
|
||||
enc.writeKeyValue(Key{keyName}, fieldVal, true)
|
||||
if fieldIndex[0] != len(fields)-1 {
|
||||
enc.wf(", ")
|
||||
}
|
||||
} else {
|
||||
enc.encode(key.add(keyName), fieldVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if inline {
|
||||
enc.wf("{")
|
||||
}
|
||||
writeFields(fieldsDirect)
|
||||
writeFields(fieldsSub)
|
||||
if inline {
|
||||
enc.wf("}")
|
||||
}
|
||||
}
|
||||
|
||||
// tomlTypeName returns the TOML type name of the Go value's type. It is
|
||||
// used to determine whether the types of array elements are mixed (which is
|
||||
// forbidden). If the Go value is nil, then it is illegal for it to be an array
|
||||
// element, and valueIsNil is returned as true.
|
||||
|
||||
// Returns the TOML type of a Go value. The type may be `nil`, which means
|
||||
// no concrete TOML type could be found.
|
||||
// tomlTypeOfGo returns the TOML type name of the Go value's type.
|
||||
//
|
||||
// It is used to determine whether the types of array elements are mixed (which
|
||||
// is forbidden). If the Go value is nil, then it is illegal for it to be an
|
||||
// array element, and valueIsNil is returned as true.
|
||||
//
|
||||
// The type may be `nil`, which means no concrete TOML type could be found.
|
||||
func tomlTypeOfGo(rv reflect.Value) tomlType {
|
||||
if isNil(rv) || !rv.IsValid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if rv.Kind() == reflect.Struct {
|
||||
if rv.Type() == timeType {
|
||||
return tomlDatetime
|
||||
}
|
||||
if isMarshaler(rv) {
|
||||
return tomlString
|
||||
}
|
||||
return tomlHash
|
||||
}
|
||||
|
||||
if isMarshaler(rv) {
|
||||
return tomlString
|
||||
}
|
||||
|
||||
switch rv.Kind() {
|
||||
case reflect.Bool:
|
||||
return tomlBool
|
||||
|
@ -397,7 +574,7 @@ func tomlTypeOfGo(rv reflect.Value) tomlType {
|
|||
case reflect.Float32, reflect.Float64:
|
||||
return tomlFloat
|
||||
case reflect.Array, reflect.Slice:
|
||||
if typeEqual(tomlHash, tomlArrayType(rv)) {
|
||||
if isTableArray(rv) {
|
||||
return tomlArrayHash
|
||||
}
|
||||
return tomlArray
|
||||
|
@ -407,54 +584,35 @@ func tomlTypeOfGo(rv reflect.Value) tomlType {
|
|||
return tomlString
|
||||
case reflect.Map:
|
||||
return tomlHash
|
||||
case reflect.Struct:
|
||||
switch rv.Interface().(type) {
|
||||
case time.Time:
|
||||
return tomlDatetime
|
||||
case TextMarshaler:
|
||||
return tomlString
|
||||
default:
|
||||
return tomlHash
|
||||
}
|
||||
default:
|
||||
panic("unexpected reflect.Kind: " + rv.Kind().String())
|
||||
encPanic(errors.New("unsupported type: " + rv.Kind().String()))
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
// tomlArrayType returns the element type of a TOML array. The type returned
|
||||
// may be nil if it cannot be determined (e.g., a nil slice or a zero length
|
||||
// slize). This function may also panic if it finds a type that cannot be
|
||||
// expressed in TOML (such as nil elements, heterogeneous arrays or directly
|
||||
// nested arrays of tables).
|
||||
func tomlArrayType(rv reflect.Value) tomlType {
|
||||
if isNil(rv) || !rv.IsValid() || rv.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
firstType := tomlTypeOfGo(rv.Index(0))
|
||||
if firstType == nil {
|
||||
encPanic(errArrayNilElement)
|
||||
func isMarshaler(rv reflect.Value) bool {
|
||||
return rv.Type().Implements(marshalText) || rv.Type().Implements(marshalToml)
|
||||
}
|
||||
|
||||
// isTableArray reports if all entries in the array or slice are a table.
|
||||
func isTableArray(arr reflect.Value) bool {
|
||||
if isNil(arr) || !arr.IsValid() || arr.Len() == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
rvlen := rv.Len()
|
||||
for i := 1; i < rvlen; i++ {
|
||||
elem := rv.Index(i)
|
||||
switch elemType := tomlTypeOfGo(elem); {
|
||||
case elemType == nil:
|
||||
ret := true
|
||||
for i := 0; i < arr.Len(); i++ {
|
||||
tt := tomlTypeOfGo(eindirect(arr.Index(i)))
|
||||
// Don't allow nil.
|
||||
if tt == nil {
|
||||
encPanic(errArrayNilElement)
|
||||
case !typeEqual(firstType, elemType):
|
||||
encPanic(errArrayMixedElementTypes)
|
||||
}
|
||||
|
||||
if ret && !typeEqual(tomlHash, tt) {
|
||||
ret = false
|
||||
}
|
||||
}
|
||||
// If we have a nested array, then we must make sure that the nested
|
||||
// array contains ONLY primitives.
|
||||
// This checks arbitrarily nested arrays.
|
||||
if typeEqual(firstType, tomlArray) || typeEqual(firstType, tomlArrayHash) {
|
||||
nest := tomlArrayType(eindirect(rv.Index(0)))
|
||||
if typeEqual(nest, tomlHash) || typeEqual(nest, tomlArrayHash) {
|
||||
encPanic(errArrayNoTable)
|
||||
}
|
||||
}
|
||||
return firstType
|
||||
return ret
|
||||
}
|
||||
|
||||
type tagOptions struct {
|
||||
|
@ -499,8 +657,26 @@ func isEmpty(rv reflect.Value) bool {
|
|||
switch rv.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
|
||||
return rv.Len() == 0
|
||||
case reflect.Struct:
|
||||
if rv.Type().Comparable() {
|
||||
return reflect.Zero(rv.Type()).Interface() == rv.Interface()
|
||||
}
|
||||
// Need to also check if all the fields are empty, otherwise something
|
||||
// like this with uncomparable types will always return true:
|
||||
//
|
||||
// type a struct{ field b }
|
||||
// type b struct{ s []string }
|
||||
// s := a{field: b{s: []string{"AAA"}}}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if !isEmpty(rv.Field(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case reflect.Bool:
|
||||
return !rv.Bool()
|
||||
case reflect.Ptr:
|
||||
return rv.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -511,18 +687,34 @@ func (enc *Encoder) newline() {
|
|||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) keyEqElement(key Key, val reflect.Value) {
|
||||
// Write a key/value pair:
|
||||
//
|
||||
// key = <any value>
|
||||
//
|
||||
// This is also used for "k = v" in inline tables; so something like this will
|
||||
// be written in three calls:
|
||||
//
|
||||
// ┌───────────────────┐
|
||||
// │ ┌───┐ ┌────┐│
|
||||
// v v v v vv
|
||||
// key = {k = 1, k2 = 2}
|
||||
func (enc *Encoder) writeKeyValue(key Key, val reflect.Value, inline bool) {
|
||||
/// Marshaler used on top-level document; call eElement() to just call
|
||||
/// Marshal{TOML,Text}.
|
||||
if len(key) == 0 {
|
||||
encPanic(errNoKey)
|
||||
enc.eElement(val)
|
||||
return
|
||||
}
|
||||
panicIfInvalidKey(key)
|
||||
enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1))
|
||||
enc.eElement(val)
|
||||
enc.newline()
|
||||
if !inline {
|
||||
enc.newline()
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) wf(format string, v ...interface{}) {
|
||||
if _, err := fmt.Fprintf(enc.w, format, v...); err != nil {
|
||||
_, err := fmt.Fprintf(enc.w, format, v...)
|
||||
if err != nil {
|
||||
encPanic(err)
|
||||
}
|
||||
enc.hasWritten = true
|
||||
|
@ -536,13 +728,25 @@ func encPanic(err error) {
|
|||
panic(tomlEncodeError{err})
|
||||
}
|
||||
|
||||
// Resolve any level of pointers to the actual value (e.g. **string → string).
|
||||
func eindirect(v reflect.Value) reflect.Value {
|
||||
switch v.Kind() {
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
return eindirect(v.Elem())
|
||||
default:
|
||||
if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface {
|
||||
if isMarshaler(v) {
|
||||
return v
|
||||
}
|
||||
if v.CanAddr() { /// Special case for marshalers; see #358.
|
||||
if pv := v.Addr(); isMarshaler(pv) {
|
||||
return pv
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
if v.IsNil() {
|
||||
return v
|
||||
}
|
||||
|
||||
return eindirect(v.Elem())
|
||||
}
|
||||
|
||||
func isNil(rv reflect.Value) bool {
|
||||
|
@ -553,16 +757,3 @@ func isNil(rv reflect.Value) bool {
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func panicIfInvalidKey(key Key) {
|
||||
for _, k := range key {
|
||||
if len(k) == 0 {
|
||||
encPanic(e("Key '%s' is not a valid table name. Key names "+
|
||||
"cannot be empty.", key.maybeQuotedAll()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isValidKeyName(s string) bool {
|
||||
return len(s) != 0
|
||||
}
|
||||
|
|
19
vendor/github.com/BurntSushi/toml/encoding_types.go
generated
vendored
19
vendor/github.com/BurntSushi/toml/encoding_types.go
generated
vendored
|
@ -1,19 +0,0 @@
|
|||
// +build go1.2
|
||||
|
||||
package toml
|
||||
|
||||
// In order to support Go 1.1, we define our own TextMarshaler and
|
||||
// TextUnmarshaler types. For Go 1.2+, we just alias them with the
|
||||
// standard library interfaces.
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
)
|
||||
|
||||
// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
|
||||
// so that Go 1.1 can be supported.
|
||||
type TextMarshaler encoding.TextMarshaler
|
||||
|
||||
// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
|
||||
// here so that Go 1.1 can be supported.
|
||||
type TextUnmarshaler encoding.TextUnmarshaler
|
18
vendor/github.com/BurntSushi/toml/encoding_types_1.1.go
generated
vendored
18
vendor/github.com/BurntSushi/toml/encoding_types_1.1.go
generated
vendored
|
@ -1,18 +0,0 @@
|
|||
// +build !go1.2
|
||||
|
||||
package toml
|
||||
|
||||
// These interfaces were introduced in Go 1.2, so we add them manually when
|
||||
// compiling for Go 1.1.
|
||||
|
||||
// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
|
||||
// so that Go 1.1 can be supported.
|
||||
type TextMarshaler interface {
|
||||
MarshalText() (text []byte, err error)
|
||||
}
|
||||
|
||||
// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
|
||||
// here so that Go 1.1 can be supported.
|
||||
type TextUnmarshaler interface {
|
||||
UnmarshalText(text []byte) error
|
||||
}
|
279
vendor/github.com/BurntSushi/toml/error.go
generated
vendored
Normal file
279
vendor/github.com/BurntSushi/toml/error.go
generated
vendored
Normal file
|
@ -0,0 +1,279 @@
|
|||
package toml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ParseError is returned when there is an error parsing the TOML syntax such as
|
||||
// invalid syntax, duplicate keys, etc.
|
||||
//
|
||||
// In addition to the error message itself, you can also print detailed location
|
||||
// information with context by using [ErrorWithPosition]:
|
||||
//
|
||||
// toml: error: Key 'fruit' was already created and cannot be used as an array.
|
||||
//
|
||||
// At line 4, column 2-7:
|
||||
//
|
||||
// 2 | fruit = []
|
||||
// 3 |
|
||||
// 4 | [[fruit]] # Not allowed
|
||||
// ^^^^^
|
||||
//
|
||||
// [ErrorWithUsage] can be used to print the above with some more detailed usage
|
||||
// guidance:
|
||||
//
|
||||
// toml: error: newlines not allowed within inline tables
|
||||
//
|
||||
// At line 1, column 18:
|
||||
//
|
||||
// 1 | x = [{ key = 42 #
|
||||
// ^
|
||||
//
|
||||
// Error help:
|
||||
//
|
||||
// Inline tables must always be on a single line:
|
||||
//
|
||||
// table = {key = 42, second = 43}
|
||||
//
|
||||
// It is invalid to split them over multiple lines like so:
|
||||
//
|
||||
// # INVALID
|
||||
// table = {
|
||||
// key = 42,
|
||||
// second = 43
|
||||
// }
|
||||
//
|
||||
// Use regular for this:
|
||||
//
|
||||
// [table]
|
||||
// key = 42
|
||||
// second = 43
|
||||
type ParseError struct {
|
||||
Message string // Short technical message.
|
||||
Usage string // Longer message with usage guidance; may be blank.
|
||||
Position Position // Position of the error
|
||||
LastKey string // Last parsed key, may be blank.
|
||||
|
||||
// Line the error occurred.
|
||||
//
|
||||
// Deprecated: use [Position].
|
||||
Line int
|
||||
|
||||
err error
|
||||
input string
|
||||
}
|
||||
|
||||
// Position of an error.
|
||||
type Position struct {
|
||||
Line int // Line number, starting at 1.
|
||||
Start int // Start of error, as byte offset starting at 0.
|
||||
Len int // Lenght in bytes.
|
||||
}
|
||||
|
||||
func (pe ParseError) Error() string {
|
||||
msg := pe.Message
|
||||
if msg == "" { // Error from errorf()
|
||||
msg = pe.err.Error()
|
||||
}
|
||||
|
||||
if pe.LastKey == "" {
|
||||
return fmt.Sprintf("toml: line %d: %s", pe.Position.Line, msg)
|
||||
}
|
||||
return fmt.Sprintf("toml: line %d (last key %q): %s",
|
||||
pe.Position.Line, pe.LastKey, msg)
|
||||
}
|
||||
|
||||
// ErrorWithPosition returns the error with detailed location context.
|
||||
//
|
||||
// See the documentation on [ParseError].
|
||||
func (pe ParseError) ErrorWithPosition() string {
|
||||
if pe.input == "" { // Should never happen, but just in case.
|
||||
return pe.Error()
|
||||
}
|
||||
|
||||
var (
|
||||
lines = strings.Split(pe.input, "\n")
|
||||
col = pe.column(lines)
|
||||
b = new(strings.Builder)
|
||||
)
|
||||
|
||||
msg := pe.Message
|
||||
if msg == "" {
|
||||
msg = pe.err.Error()
|
||||
}
|
||||
|
||||
// TODO: don't show control characters as literals? This may not show up
|
||||
// well everywhere.
|
||||
|
||||
if pe.Position.Len == 1 {
|
||||
fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d:\n\n",
|
||||
msg, pe.Position.Line, col+1)
|
||||
} else {
|
||||
fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d-%d:\n\n",
|
||||
msg, pe.Position.Line, col, col+pe.Position.Len)
|
||||
}
|
||||
if pe.Position.Line > 2 {
|
||||
fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, lines[pe.Position.Line-3])
|
||||
}
|
||||
if pe.Position.Line > 1 {
|
||||
fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-1, lines[pe.Position.Line-2])
|
||||
}
|
||||
fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, lines[pe.Position.Line-1])
|
||||
fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", col), strings.Repeat("^", pe.Position.Len))
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// ErrorWithUsage returns the error with detailed location context and usage
|
||||
// guidance.
|
||||
//
|
||||
// See the documentation on [ParseError].
|
||||
func (pe ParseError) ErrorWithUsage() string {
|
||||
m := pe.ErrorWithPosition()
|
||||
if u, ok := pe.err.(interface{ Usage() string }); ok && u.Usage() != "" {
|
||||
lines := strings.Split(strings.TrimSpace(u.Usage()), "\n")
|
||||
for i := range lines {
|
||||
if lines[i] != "" {
|
||||
lines[i] = " " + lines[i]
|
||||
}
|
||||
}
|
||||
return m + "Error help:\n\n" + strings.Join(lines, "\n") + "\n"
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (pe ParseError) column(lines []string) int {
|
||||
var pos, col int
|
||||
for i := range lines {
|
||||
ll := len(lines[i]) + 1 // +1 for the removed newline
|
||||
if pos+ll >= pe.Position.Start {
|
||||
col = pe.Position.Start - pos
|
||||
if col < 0 { // Should never happen, but just in case.
|
||||
col = 0
|
||||
}
|
||||
break
|
||||
}
|
||||
pos += ll
|
||||
}
|
||||
|
||||
return col
|
||||
}
|
||||
|
||||
type (
|
||||
errLexControl struct{ r rune }
|
||||
errLexEscape struct{ r rune }
|
||||
errLexUTF8 struct{ b byte }
|
||||
errLexInvalidNum struct{ v string }
|
||||
errLexInvalidDate struct{ v string }
|
||||
errLexInlineTableNL struct{}
|
||||
errLexStringNL struct{}
|
||||
errParseRange struct {
|
||||
i interface{} // int or float
|
||||
size string // "int64", "uint16", etc.
|
||||
}
|
||||
errParseDuration struct{ d string }
|
||||
)
|
||||
|
||||
func (e errLexControl) Error() string {
|
||||
return fmt.Sprintf("TOML files cannot contain control characters: '0x%02x'", e.r)
|
||||
}
|
||||
func (e errLexControl) Usage() string { return "" }
|
||||
|
||||
func (e errLexEscape) Error() string { return fmt.Sprintf(`invalid escape in string '\%c'`, e.r) }
|
||||
func (e errLexEscape) Usage() string { return usageEscape }
|
||||
func (e errLexUTF8) Error() string { return fmt.Sprintf("invalid UTF-8 byte: 0x%02x", e.b) }
|
||||
func (e errLexUTF8) Usage() string { return "" }
|
||||
func (e errLexInvalidNum) Error() string { return fmt.Sprintf("invalid number: %q", e.v) }
|
||||
func (e errLexInvalidNum) Usage() string { return "" }
|
||||
func (e errLexInvalidDate) Error() string { return fmt.Sprintf("invalid date: %q", e.v) }
|
||||
func (e errLexInvalidDate) Usage() string { return "" }
|
||||
func (e errLexInlineTableNL) Error() string { return "newlines not allowed within inline tables" }
|
||||
func (e errLexInlineTableNL) Usage() string { return usageInlineNewline }
|
||||
func (e errLexStringNL) Error() string { return "strings cannot contain newlines" }
|
||||
func (e errLexStringNL) Usage() string { return usageStringNewline }
|
||||
func (e errParseRange) Error() string { return fmt.Sprintf("%v is out of range for %s", e.i, e.size) }
|
||||
func (e errParseRange) Usage() string { return usageIntOverflow }
|
||||
func (e errParseDuration) Error() string { return fmt.Sprintf("invalid duration: %q", e.d) }
|
||||
func (e errParseDuration) Usage() string { return usageDuration }
|
||||
|
||||
const usageEscape = `
|
||||
A '\' inside a "-delimited string is interpreted as an escape character.
|
||||
|
||||
The following escape sequences are supported:
|
||||
\b, \t, \n, \f, \r, \", \\, \uXXXX, and \UXXXXXXXX
|
||||
|
||||
To prevent a '\' from being recognized as an escape character, use either:
|
||||
|
||||
- a ' or '''-delimited string; escape characters aren't processed in them; or
|
||||
- write two backslashes to get a single backslash: '\\'.
|
||||
|
||||
If you're trying to add a Windows path (e.g. "C:\Users\martin") then using '/'
|
||||
instead of '\' will usually also work: "C:/Users/martin".
|
||||
`
|
||||
|
||||
const usageInlineNewline = `
|
||||
Inline tables must always be on a single line:
|
||||
|
||||
table = {key = 42, second = 43}
|
||||
|
||||
It is invalid to split them over multiple lines like so:
|
||||
|
||||
# INVALID
|
||||
table = {
|
||||
key = 42,
|
||||
second = 43
|
||||
}
|
||||
|
||||
Use regular for this:
|
||||
|
||||
[table]
|
||||
key = 42
|
||||
second = 43
|
||||
`
|
||||
|
||||
const usageStringNewline = `
|
||||
Strings must always be on a single line, and cannot span more than one line:
|
||||
|
||||
# INVALID
|
||||
string = "Hello,
|
||||
world!"
|
||||
|
||||
Instead use """ or ''' to split strings over multiple lines:
|
||||
|
||||
string = """Hello,
|
||||
world!"""
|
||||
`
|
||||
|
||||
const usageIntOverflow = `
|
||||
This number is too large; this may be an error in the TOML, but it can also be a
|
||||
bug in the program that uses too small of an integer.
|
||||
|
||||
The maximum and minimum values are:
|
||||
|
||||
size │ lowest │ highest
|
||||
───────┼────────────────┼──────────
|
||||
int8 │ -128 │ 127
|
||||
int16 │ -32,768 │ 32,767
|
||||
int32 │ -2,147,483,648 │ 2,147,483,647
|
||||
int64 │ -9.2 × 10¹⁷ │ 9.2 × 10¹⁷
|
||||
uint8 │ 0 │ 255
|
||||
uint16 │ 0 │ 65535
|
||||
uint32 │ 0 │ 4294967295
|
||||
uint64 │ 0 │ 1.8 × 10¹⁸
|
||||
|
||||
int refers to int32 on 32-bit systems and int64 on 64-bit systems.
|
||||
`
|
||||
|
||||
const usageDuration = `
|
||||
A duration must be as "number<unit>", without any spaces. Valid units are:
|
||||
|
||||
ns nanoseconds (billionth of a second)
|
||||
us, µs microseconds (millionth of a second)
|
||||
ms milliseconds (thousands of a second)
|
||||
s seconds
|
||||
m minutes
|
||||
h hours
|
||||
|
||||
You can combine multiple units; for example "5m10s" for 5 minutes and 10
|
||||
seconds.
|
||||
`
|
36
vendor/github.com/BurntSushi/toml/internal/tz.go
generated
vendored
Normal file
36
vendor/github.com/BurntSushi/toml/internal/tz.go
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
package internal
|
||||
|
||||
import "time"
|
||||
|
||||
// Timezones used for local datetime, date, and time TOML types.
|
||||
//
|
||||
// The exact way times and dates without a timezone should be interpreted is not
|
||||
// well-defined in the TOML specification and left to the implementation. These
|
||||
// defaults to current local timezone offset of the computer, but this can be
|
||||
// changed by changing these variables before decoding.
|
||||
//
|
||||
// TODO:
|
||||
// Ideally we'd like to offer people the ability to configure the used timezone
|
||||
// by setting Decoder.Timezone and Encoder.Timezone; however, this is a bit
|
||||
// tricky: the reason we use three different variables for this is to support
|
||||
// round-tripping – without these specific TZ names we wouldn't know which
|
||||
// format to use.
|
||||
//
|
||||
// There isn't a good way to encode this right now though, and passing this sort
|
||||
// of information also ties in to various related issues such as string format
|
||||
// encoding, encoding of comments, etc.
|
||||
//
|
||||
// So, for the time being, just put this in internal until we can write a good
|
||||
// comprehensive API for doing all of this.
|
||||
//
|
||||
// The reason they're exported is because they're referred from in e.g.
|
||||
// internal/tag.
|
||||
//
|
||||
// Note that this behaviour is valid according to the TOML spec as the exact
|
||||
// behaviour is left up to implementations.
|
||||
var (
|
||||
localOffset = func() int { _, o := time.Now().Zone(); return o }()
|
||||
LocalDatetime = time.FixedZone("datetime-local", localOffset)
|
||||
LocalDate = time.FixedZone("date-local", localOffset)
|
||||
LocalTime = time.FixedZone("time-local", localOffset)
|
||||
)
|
866
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
866
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
File diff suppressed because it is too large
Load diff
126
vendor/github.com/BurntSushi/toml/decode_meta.go → vendor/github.com/BurntSushi/toml/meta.go
generated
vendored
126
vendor/github.com/BurntSushi/toml/decode_meta.go → vendor/github.com/BurntSushi/toml/meta.go
generated
vendored
|
@ -1,33 +1,40 @@
|
|||
package toml
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MetaData allows access to meta information about TOML data that may not
|
||||
// be inferrable via reflection. In particular, whether a key has been defined
|
||||
// and the TOML type of a key.
|
||||
// MetaData allows access to meta information about TOML data that's not
|
||||
// accessible otherwise.
|
||||
//
|
||||
// It allows checking if a key is defined in the TOML data, whether any keys
|
||||
// were undecoded, and the TOML type of a key.
|
||||
type MetaData struct {
|
||||
mapping map[string]interface{}
|
||||
types map[string]tomlType
|
||||
keys []Key
|
||||
decoded map[string]bool
|
||||
context Key // Used only during decoding.
|
||||
|
||||
keyInfo map[string]keyInfo
|
||||
mapping map[string]interface{}
|
||||
keys []Key
|
||||
decoded map[string]struct{}
|
||||
data []byte // Input file; for errors.
|
||||
}
|
||||
|
||||
// IsDefined returns true if the key given exists in the TOML data. The key
|
||||
// should be specified hierarchially. e.g.,
|
||||
// IsDefined reports if the key exists in the TOML data.
|
||||
//
|
||||
// // access the TOML key 'a.b.c'
|
||||
// IsDefined("a", "b", "c")
|
||||
// The key should be specified hierarchically, for example to access the TOML
|
||||
// key "a.b.c" you would use IsDefined("a", "b", "c"). Keys are case sensitive.
|
||||
//
|
||||
// IsDefined will return false if an empty key given. Keys are case sensitive.
|
||||
// Returns false for an empty key.
|
||||
func (md *MetaData) IsDefined(key ...string) bool {
|
||||
if len(key) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var hash map[string]interface{}
|
||||
var ok bool
|
||||
var hashOrVal interface{} = md.mapping
|
||||
var (
|
||||
hash map[string]interface{}
|
||||
ok bool
|
||||
hashOrVal interface{} = md.mapping
|
||||
)
|
||||
for _, k := range key {
|
||||
if hash, ok = hashOrVal.(map[string]interface{}); !ok {
|
||||
return false
|
||||
|
@ -41,58 +48,20 @@ func (md *MetaData) IsDefined(key ...string) bool {
|
|||
|
||||
// Type returns a string representation of the type of the key specified.
|
||||
//
|
||||
// Type will return the empty string if given an empty key or a key that
|
||||
// does not exist. Keys are case sensitive.
|
||||
// Type will return the empty string if given an empty key or a key that does
|
||||
// not exist. Keys are case sensitive.
|
||||
func (md *MetaData) Type(key ...string) string {
|
||||
fullkey := strings.Join(key, ".")
|
||||
if typ, ok := md.types[fullkey]; ok {
|
||||
return typ.typeString()
|
||||
if ki, ok := md.keyInfo[Key(key).String()]; ok {
|
||||
return ki.tomlType.typeString()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Key is the type of any TOML key, including key groups. Use (MetaData).Keys
|
||||
// to get values of this type.
|
||||
type Key []string
|
||||
|
||||
func (k Key) String() string {
|
||||
return strings.Join(k, ".")
|
||||
}
|
||||
|
||||
func (k Key) maybeQuotedAll() string {
|
||||
var ss []string
|
||||
for i := range k {
|
||||
ss = append(ss, k.maybeQuoted(i))
|
||||
}
|
||||
return strings.Join(ss, ".")
|
||||
}
|
||||
|
||||
func (k Key) maybeQuoted(i int) string {
|
||||
quote := false
|
||||
for _, c := range k[i] {
|
||||
if !isBareKeyChar(c) {
|
||||
quote = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if quote {
|
||||
return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\""
|
||||
}
|
||||
return k[i]
|
||||
}
|
||||
|
||||
func (k Key) add(piece string) Key {
|
||||
newKey := make(Key, len(k)+1)
|
||||
copy(newKey, k)
|
||||
newKey[len(k)] = piece
|
||||
return newKey
|
||||
}
|
||||
|
||||
// Keys returns a slice of every key in the TOML data, including key groups.
|
||||
// Each key is itself a slice, where the first element is the top of the
|
||||
// hierarchy and the last is the most specific.
|
||||
//
|
||||
// The list will have the same order as the keys appeared in the TOML data.
|
||||
// Each key is itself a slice, where the first element is the top of the
|
||||
// hierarchy and the last is the most specific. The list will have the same
|
||||
// order as the keys appeared in the TOML data.
|
||||
//
|
||||
// All keys returned are non-empty.
|
||||
func (md *MetaData) Keys() []Key {
|
||||
|
@ -102,7 +71,7 @@ func (md *MetaData) Keys() []Key {
|
|||
// Undecoded returns all keys that have not been decoded in the order in which
|
||||
// they appear in the original TOML document.
|
||||
//
|
||||
// This includes keys that haven't been decoded because of a Primitive value.
|
||||
// This includes keys that haven't been decoded because of a [Primitive] value.
|
||||
// Once the Primitive value is decoded, the keys will be considered decoded.
|
||||
//
|
||||
// Also note that decoding into an empty interface will result in no decoding,
|
||||
|
@ -113,9 +82,40 @@ func (md *MetaData) Keys() []Key {
|
|||
func (md *MetaData) Undecoded() []Key {
|
||||
undecoded := make([]Key, 0, len(md.keys))
|
||||
for _, key := range md.keys {
|
||||
if !md.decoded[key.String()] {
|
||||
if _, ok := md.decoded[key.String()]; !ok {
|
||||
undecoded = append(undecoded, key)
|
||||
}
|
||||
}
|
||||
return undecoded
|
||||
}
|
||||
|
||||
// Key represents any TOML key, including key groups. Use [MetaData.Keys] to get
|
||||
// values of this type.
|
||||
type Key []string
|
||||
|
||||
func (k Key) String() string {
|
||||
ss := make([]string, len(k))
|
||||
for i := range k {
|
||||
ss[i] = k.maybeQuoted(i)
|
||||
}
|
||||
return strings.Join(ss, ".")
|
||||
}
|
||||
|
||||
func (k Key) maybeQuoted(i int) string {
|
||||
if k[i] == "" {
|
||||
return `""`
|
||||
}
|
||||
for _, c := range k[i] {
|
||||
if !isBareKeyChar(c, false) {
|
||||
return `"` + dblQuotedReplacer.Replace(k[i]) + `"`
|
||||
}
|
||||
}
|
||||
return k[i]
|
||||
}
|
||||
|
||||
func (k Key) add(piece string) Key {
|
||||
newKey := make(Key, len(k)+1)
|
||||
copy(newKey, k)
|
||||
newKey[len(k)] = piece
|
||||
return newKey
|
||||
}
|
729
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
729
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
|
@ -2,57 +2,80 @@ package toml
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/BurntSushi/toml/internal"
|
||||
)
|
||||
|
||||
type parser struct {
|
||||
mapping map[string]interface{}
|
||||
types map[string]tomlType
|
||||
lx *lexer
|
||||
lx *lexer
|
||||
context Key // Full key for the current hash in scope.
|
||||
currentKey string // Base key name for everything except hashes.
|
||||
pos Position // Current position in the TOML file.
|
||||
tomlNext bool
|
||||
|
||||
// A list of keys in the order that they appear in the TOML data.
|
||||
ordered []Key
|
||||
ordered []Key // List of keys in the order that they appear in the TOML data.
|
||||
|
||||
// the full key for the current hash in scope
|
||||
context Key
|
||||
|
||||
// the base key name for everything except hashes
|
||||
currentKey string
|
||||
|
||||
// rough approximation of line number
|
||||
approxLine int
|
||||
|
||||
// A map of 'key.group.names' to whether they were created implicitly.
|
||||
implicits map[string]bool
|
||||
keyInfo map[string]keyInfo // Map keyname → info about the TOML key.
|
||||
mapping map[string]interface{} // Map keyname → key value.
|
||||
implicits map[string]struct{} // Record implicit keys (e.g. "key.group.names").
|
||||
}
|
||||
|
||||
type parseError string
|
||||
|
||||
func (pe parseError) Error() string {
|
||||
return string(pe)
|
||||
type keyInfo struct {
|
||||
pos Position
|
||||
tomlType tomlType
|
||||
}
|
||||
|
||||
func parse(data string) (p *parser, err error) {
|
||||
_, tomlNext := os.LookupEnv("BURNTSUSHI_TOML_110")
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
var ok bool
|
||||
if err, ok = r.(parseError); ok {
|
||||
if pErr, ok := r.(ParseError); ok {
|
||||
pErr.input = data
|
||||
err = pErr
|
||||
return
|
||||
}
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
|
||||
// Read over BOM; do this here as the lexer calls utf8.DecodeRuneInString()
|
||||
// which mangles stuff. UTF-16 BOM isn't strictly valid, but some tools add
|
||||
// it anyway.
|
||||
if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { // UTF-16
|
||||
data = data[2:]
|
||||
} else if strings.HasPrefix(data, "\xef\xbb\xbf") { // UTF-8
|
||||
data = data[3:]
|
||||
}
|
||||
|
||||
// Examine first few bytes for NULL bytes; this probably means it's a UTF-16
|
||||
// file (second byte in surrogate pair being NULL). Again, do this here to
|
||||
// avoid having to deal with UTF-8/16 stuff in the lexer.
|
||||
ex := 6
|
||||
if len(data) < 6 {
|
||||
ex = len(data)
|
||||
}
|
||||
if i := strings.IndexRune(data[:ex], 0); i > -1 {
|
||||
return nil, ParseError{
|
||||
Message: "files cannot contain NULL bytes; probably using UTF-16; TOML files must be UTF-8",
|
||||
Position: Position{Line: 1, Start: i, Len: 1},
|
||||
Line: 1,
|
||||
input: data,
|
||||
}
|
||||
}
|
||||
|
||||
p = &parser{
|
||||
keyInfo: make(map[string]keyInfo),
|
||||
mapping: make(map[string]interface{}),
|
||||
types: make(map[string]tomlType),
|
||||
lx: lex(data),
|
||||
lx: lex(data, tomlNext),
|
||||
ordered: make([]Key, 0),
|
||||
implicits: make(map[string]bool),
|
||||
implicits: make(map[string]struct{}),
|
||||
tomlNext: tomlNext,
|
||||
}
|
||||
for {
|
||||
item := p.next()
|
||||
|
@ -65,20 +88,57 @@ func parse(data string) (p *parser, err error) {
|
|||
return p, nil
|
||||
}
|
||||
|
||||
func (p *parser) panicErr(it item, err error) {
|
||||
panic(ParseError{
|
||||
err: err,
|
||||
Position: it.pos,
|
||||
Line: it.pos.Len,
|
||||
LastKey: p.current(),
|
||||
})
|
||||
}
|
||||
|
||||
func (p *parser) panicItemf(it item, format string, v ...interface{}) {
|
||||
panic(ParseError{
|
||||
Message: fmt.Sprintf(format, v...),
|
||||
Position: it.pos,
|
||||
Line: it.pos.Len,
|
||||
LastKey: p.current(),
|
||||
})
|
||||
}
|
||||
|
||||
func (p *parser) panicf(format string, v ...interface{}) {
|
||||
msg := fmt.Sprintf("Near line %d (last key parsed '%s'): %s",
|
||||
p.approxLine, p.current(), fmt.Sprintf(format, v...))
|
||||
panic(parseError(msg))
|
||||
panic(ParseError{
|
||||
Message: fmt.Sprintf(format, v...),
|
||||
Position: p.pos,
|
||||
Line: p.pos.Line,
|
||||
LastKey: p.current(),
|
||||
})
|
||||
}
|
||||
|
||||
func (p *parser) next() item {
|
||||
it := p.lx.nextItem()
|
||||
//fmt.Printf("ITEM %-18s line %-3d │ %q\n", it.typ, it.pos.Line, it.val)
|
||||
if it.typ == itemError {
|
||||
p.panicf("%s", it.val)
|
||||
if it.err != nil {
|
||||
panic(ParseError{
|
||||
Position: it.pos,
|
||||
Line: it.pos.Line,
|
||||
LastKey: p.current(),
|
||||
err: it.err,
|
||||
})
|
||||
}
|
||||
|
||||
p.panicItemf(it, "%s", it.val)
|
||||
}
|
||||
return it
|
||||
}
|
||||
|
||||
func (p *parser) nextPos() item {
|
||||
it := p.next()
|
||||
p.pos = it.pos
|
||||
return it
|
||||
}
|
||||
|
||||
func (p *parser) bug(format string, v ...interface{}) {
|
||||
panic(fmt.Sprintf("BUG: "+format+"\n\n", v...))
|
||||
}
|
||||
|
@ -97,44 +157,60 @@ func (p *parser) assertEqual(expected, got itemType) {
|
|||
|
||||
func (p *parser) topLevel(item item) {
|
||||
switch item.typ {
|
||||
case itemCommentStart:
|
||||
p.approxLine = item.line
|
||||
case itemCommentStart: // # ..
|
||||
p.expect(itemText)
|
||||
case itemTableStart:
|
||||
kg := p.next()
|
||||
p.approxLine = kg.line
|
||||
case itemTableStart: // [ .. ]
|
||||
name := p.nextPos()
|
||||
|
||||
var key Key
|
||||
for ; kg.typ != itemTableEnd && kg.typ != itemEOF; kg = p.next() {
|
||||
key = append(key, p.keyString(kg))
|
||||
for ; name.typ != itemTableEnd && name.typ != itemEOF; name = p.next() {
|
||||
key = append(key, p.keyString(name))
|
||||
}
|
||||
p.assertEqual(itemTableEnd, kg.typ)
|
||||
p.assertEqual(itemTableEnd, name.typ)
|
||||
|
||||
p.establishContext(key, false)
|
||||
p.setType("", tomlHash)
|
||||
p.addContext(key, false)
|
||||
p.setType("", tomlHash, item.pos)
|
||||
p.ordered = append(p.ordered, key)
|
||||
case itemArrayTableStart:
|
||||
kg := p.next()
|
||||
p.approxLine = kg.line
|
||||
case itemArrayTableStart: // [[ .. ]]
|
||||
name := p.nextPos()
|
||||
|
||||
var key Key
|
||||
for ; kg.typ != itemArrayTableEnd && kg.typ != itemEOF; kg = p.next() {
|
||||
key = append(key, p.keyString(kg))
|
||||
for ; name.typ != itemArrayTableEnd && name.typ != itemEOF; name = p.next() {
|
||||
key = append(key, p.keyString(name))
|
||||
}
|
||||
p.assertEqual(itemArrayTableEnd, kg.typ)
|
||||
p.assertEqual(itemArrayTableEnd, name.typ)
|
||||
|
||||
p.establishContext(key, true)
|
||||
p.setType("", tomlArrayHash)
|
||||
p.addContext(key, true)
|
||||
p.setType("", tomlArrayHash, item.pos)
|
||||
p.ordered = append(p.ordered, key)
|
||||
case itemKeyStart:
|
||||
kname := p.next()
|
||||
p.approxLine = kname.line
|
||||
p.currentKey = p.keyString(kname)
|
||||
case itemKeyStart: // key = ..
|
||||
outerContext := p.context
|
||||
/// Read all the key parts (e.g. 'a' and 'b' in 'a.b')
|
||||
k := p.nextPos()
|
||||
var key Key
|
||||
for ; k.typ != itemKeyEnd && k.typ != itemEOF; k = p.next() {
|
||||
key = append(key, p.keyString(k))
|
||||
}
|
||||
p.assertEqual(itemKeyEnd, k.typ)
|
||||
|
||||
val, typ := p.value(p.next())
|
||||
p.setValue(p.currentKey, val)
|
||||
p.setType(p.currentKey, typ)
|
||||
/// The current key is the last part.
|
||||
p.currentKey = key[len(key)-1]
|
||||
|
||||
/// All the other parts (if any) are the context; need to set each part
|
||||
/// as implicit.
|
||||
context := key[:len(key)-1]
|
||||
for i := range context {
|
||||
p.addImplicitContext(append(p.context, context[i:i+1]...))
|
||||
}
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
|
||||
/// Set value.
|
||||
vItem := p.next()
|
||||
val, typ := p.value(vItem, false)
|
||||
p.set(p.currentKey, val, typ, vItem.pos)
|
||||
|
||||
/// Remove the context we added (preserving any context from [tbl] lines).
|
||||
p.context = outerContext
|
||||
p.currentKey = ""
|
||||
default:
|
||||
p.bug("Unexpected type at top level: %s", item.typ)
|
||||
|
@ -148,180 +224,271 @@ func (p *parser) keyString(it item) string {
|
|||
return it.val
|
||||
case itemString, itemMultilineString,
|
||||
itemRawString, itemRawMultilineString:
|
||||
s, _ := p.value(it)
|
||||
s, _ := p.value(it, false)
|
||||
return s.(string)
|
||||
default:
|
||||
p.bug("Unexpected key type: %s", it.typ)
|
||||
panic("unreachable")
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var datetimeRepl = strings.NewReplacer(
|
||||
"z", "Z",
|
||||
"t", "T",
|
||||
" ", "T")
|
||||
|
||||
// value translates an expected value from the lexer into a Go value wrapped
|
||||
// as an empty interface.
|
||||
func (p *parser) value(it item) (interface{}, tomlType) {
|
||||
func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) {
|
||||
switch it.typ {
|
||||
case itemString:
|
||||
return p.replaceEscapes(it.val), p.typeOfPrimitive(it)
|
||||
return p.replaceEscapes(it, it.val), p.typeOfPrimitive(it)
|
||||
case itemMultilineString:
|
||||
trimmed := stripFirstNewline(stripEscapedWhitespace(it.val))
|
||||
return p.replaceEscapes(trimmed), p.typeOfPrimitive(it)
|
||||
return p.replaceEscapes(it, p.stripEscapedNewlines(stripFirstNewline(it.val))), p.typeOfPrimitive(it)
|
||||
case itemRawString:
|
||||
return it.val, p.typeOfPrimitive(it)
|
||||
case itemRawMultilineString:
|
||||
return stripFirstNewline(it.val), p.typeOfPrimitive(it)
|
||||
case itemInteger:
|
||||
return p.valueInteger(it)
|
||||
case itemFloat:
|
||||
return p.valueFloat(it)
|
||||
case itemBool:
|
||||
switch it.val {
|
||||
case "true":
|
||||
return true, p.typeOfPrimitive(it)
|
||||
case "false":
|
||||
return false, p.typeOfPrimitive(it)
|
||||
default:
|
||||
p.bug("Expected boolean value, but got '%s'.", it.val)
|
||||
}
|
||||
p.bug("Expected boolean value, but got '%s'.", it.val)
|
||||
case itemInteger:
|
||||
if !numUnderscoresOK(it.val) {
|
||||
p.panicf("Invalid integer %q: underscores must be surrounded by digits",
|
||||
it.val)
|
||||
}
|
||||
val := strings.Replace(it.val, "_", "", -1)
|
||||
num, err := strconv.ParseInt(val, 10, 64)
|
||||
if err != nil {
|
||||
// Distinguish integer values. Normally, it'd be a bug if the lexer
|
||||
// provides an invalid integer, but it's possible that the number is
|
||||
// out of range of valid values (which the lexer cannot determine).
|
||||
// So mark the former as a bug but the latter as a legitimate user
|
||||
// error.
|
||||
if e, ok := err.(*strconv.NumError); ok &&
|
||||
e.Err == strconv.ErrRange {
|
||||
|
||||
p.panicf("Integer '%s' is out of the range of 64-bit "+
|
||||
"signed integers.", it.val)
|
||||
} else {
|
||||
p.bug("Expected integer value, but got '%s'.", it.val)
|
||||
}
|
||||
}
|
||||
return num, p.typeOfPrimitive(it)
|
||||
case itemFloat:
|
||||
parts := strings.FieldsFunc(it.val, func(r rune) bool {
|
||||
switch r {
|
||||
case '.', 'e', 'E':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
for _, part := range parts {
|
||||
if !numUnderscoresOK(part) {
|
||||
p.panicf("Invalid float %q: underscores must be "+
|
||||
"surrounded by digits", it.val)
|
||||
}
|
||||
}
|
||||
if !numPeriodsOK(it.val) {
|
||||
// As a special case, numbers like '123.' or '1.e2',
|
||||
// which are valid as far as Go/strconv are concerned,
|
||||
// must be rejected because TOML says that a fractional
|
||||
// part consists of '.' followed by 1+ digits.
|
||||
p.panicf("Invalid float %q: '.' must be followed "+
|
||||
"by one or more digits", it.val)
|
||||
}
|
||||
val := strings.Replace(it.val, "_", "", -1)
|
||||
num, err := strconv.ParseFloat(val, 64)
|
||||
if err != nil {
|
||||
if e, ok := err.(*strconv.NumError); ok &&
|
||||
e.Err == strconv.ErrRange {
|
||||
|
||||
p.panicf("Float '%s' is out of the range of 64-bit "+
|
||||
"IEEE-754 floating-point numbers.", it.val)
|
||||
} else {
|
||||
p.panicf("Invalid float value: %q", it.val)
|
||||
}
|
||||
}
|
||||
return num, p.typeOfPrimitive(it)
|
||||
case itemDatetime:
|
||||
var t time.Time
|
||||
var ok bool
|
||||
var err error
|
||||
for _, format := range []string{
|
||||
"2006-01-02T15:04:05Z07:00",
|
||||
"2006-01-02T15:04:05",
|
||||
"2006-01-02",
|
||||
} {
|
||||
t, err = time.ParseInLocation(format, it.val, time.Local)
|
||||
if err == nil {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
p.panicf("Invalid TOML Datetime: %q.", it.val)
|
||||
}
|
||||
return t, p.typeOfPrimitive(it)
|
||||
return p.valueDatetime(it)
|
||||
case itemArray:
|
||||
array := make([]interface{}, 0)
|
||||
types := make([]tomlType, 0)
|
||||
|
||||
for it = p.next(); it.typ != itemArrayEnd; it = p.next() {
|
||||
if it.typ == itemCommentStart {
|
||||
p.expect(itemText)
|
||||
continue
|
||||
}
|
||||
|
||||
val, typ := p.value(it)
|
||||
array = append(array, val)
|
||||
types = append(types, typ)
|
||||
}
|
||||
return array, p.typeOfArray(types)
|
||||
return p.valueArray(it)
|
||||
case itemInlineTableStart:
|
||||
var (
|
||||
hash = make(map[string]interface{})
|
||||
outerContext = p.context
|
||||
outerKey = p.currentKey
|
||||
)
|
||||
|
||||
p.context = append(p.context, p.currentKey)
|
||||
p.currentKey = ""
|
||||
for it := p.next(); it.typ != itemInlineTableEnd; it = p.next() {
|
||||
if it.typ != itemKeyStart {
|
||||
p.bug("Expected key start but instead found %q, around line %d",
|
||||
it.val, p.approxLine)
|
||||
}
|
||||
if it.typ == itemCommentStart {
|
||||
p.expect(itemText)
|
||||
continue
|
||||
}
|
||||
|
||||
// retrieve key
|
||||
k := p.next()
|
||||
p.approxLine = k.line
|
||||
kname := p.keyString(k)
|
||||
|
||||
// retrieve value
|
||||
p.currentKey = kname
|
||||
val, typ := p.value(p.next())
|
||||
// make sure we keep metadata up to date
|
||||
p.setType(kname, typ)
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
hash[kname] = val
|
||||
}
|
||||
p.context = outerContext
|
||||
p.currentKey = outerKey
|
||||
return hash, tomlHash
|
||||
return p.valueInlineTable(it, parentIsArray)
|
||||
default:
|
||||
p.bug("Unexpected value type: %s", it.typ)
|
||||
}
|
||||
p.bug("Unexpected value type: %s", it.typ)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (p *parser) valueInteger(it item) (interface{}, tomlType) {
|
||||
if !numUnderscoresOK(it.val) {
|
||||
p.panicItemf(it, "Invalid integer %q: underscores must be surrounded by digits", it.val)
|
||||
}
|
||||
if numHasLeadingZero(it.val) {
|
||||
p.panicItemf(it, "Invalid integer %q: cannot have leading zeroes", it.val)
|
||||
}
|
||||
|
||||
num, err := strconv.ParseInt(it.val, 0, 64)
|
||||
if err != nil {
|
||||
// Distinguish integer values. Normally, it'd be a bug if the lexer
|
||||
// provides an invalid integer, but it's possible that the number is
|
||||
// out of range of valid values (which the lexer cannot determine).
|
||||
// So mark the former as a bug but the latter as a legitimate user
|
||||
// error.
|
||||
if e, ok := err.(*strconv.NumError); ok && e.Err == strconv.ErrRange {
|
||||
p.panicErr(it, errParseRange{i: it.val, size: "int64"})
|
||||
} else {
|
||||
p.bug("Expected integer value, but got '%s'.", it.val)
|
||||
}
|
||||
}
|
||||
return num, p.typeOfPrimitive(it)
|
||||
}
|
||||
|
||||
func (p *parser) valueFloat(it item) (interface{}, tomlType) {
|
||||
parts := strings.FieldsFunc(it.val, func(r rune) bool {
|
||||
switch r {
|
||||
case '.', 'e', 'E':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
for _, part := range parts {
|
||||
if !numUnderscoresOK(part) {
|
||||
p.panicItemf(it, "Invalid float %q: underscores must be surrounded by digits", it.val)
|
||||
}
|
||||
}
|
||||
if len(parts) > 0 && numHasLeadingZero(parts[0]) {
|
||||
p.panicItemf(it, "Invalid float %q: cannot have leading zeroes", it.val)
|
||||
}
|
||||
if !numPeriodsOK(it.val) {
|
||||
// As a special case, numbers like '123.' or '1.e2',
|
||||
// which are valid as far as Go/strconv are concerned,
|
||||
// must be rejected because TOML says that a fractional
|
||||
// part consists of '.' followed by 1+ digits.
|
||||
p.panicItemf(it, "Invalid float %q: '.' must be followed by one or more digits", it.val)
|
||||
}
|
||||
val := strings.Replace(it.val, "_", "", -1)
|
||||
if val == "+nan" || val == "-nan" { // Go doesn't support this, but TOML spec does.
|
||||
val = "nan"
|
||||
}
|
||||
num, err := strconv.ParseFloat(val, 64)
|
||||
if err != nil {
|
||||
if e, ok := err.(*strconv.NumError); ok && e.Err == strconv.ErrRange {
|
||||
p.panicErr(it, errParseRange{i: it.val, size: "float64"})
|
||||
} else {
|
||||
p.panicItemf(it, "Invalid float value: %q", it.val)
|
||||
}
|
||||
}
|
||||
return num, p.typeOfPrimitive(it)
|
||||
}
|
||||
|
||||
var dtTypes = []struct {
|
||||
fmt string
|
||||
zone *time.Location
|
||||
next bool
|
||||
}{
|
||||
{time.RFC3339Nano, time.Local, false},
|
||||
{"2006-01-02T15:04:05.999999999", internal.LocalDatetime, false},
|
||||
{"2006-01-02", internal.LocalDate, false},
|
||||
{"15:04:05.999999999", internal.LocalTime, false},
|
||||
|
||||
// tomlNext
|
||||
{"2006-01-02T15:04Z07:00", time.Local, true},
|
||||
{"2006-01-02T15:04", internal.LocalDatetime, true},
|
||||
{"15:04", internal.LocalTime, true},
|
||||
}
|
||||
|
||||
func (p *parser) valueDatetime(it item) (interface{}, tomlType) {
|
||||
it.val = datetimeRepl.Replace(it.val)
|
||||
var (
|
||||
t time.Time
|
||||
ok bool
|
||||
err error
|
||||
)
|
||||
for _, dt := range dtTypes {
|
||||
if dt.next && !p.tomlNext {
|
||||
continue
|
||||
}
|
||||
t, err = time.ParseInLocation(dt.fmt, it.val, dt.zone)
|
||||
if err == nil {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
p.panicItemf(it, "Invalid TOML Datetime: %q.", it.val)
|
||||
}
|
||||
return t, p.typeOfPrimitive(it)
|
||||
}
|
||||
|
||||
func (p *parser) valueArray(it item) (interface{}, tomlType) {
|
||||
p.setType(p.currentKey, tomlArray, it.pos)
|
||||
|
||||
var (
|
||||
types []tomlType
|
||||
|
||||
// Initialize to a non-nil empty slice. This makes it consistent with
|
||||
// how S = [] decodes into a non-nil slice inside something like struct
|
||||
// { S []string }. See #338
|
||||
array = []interface{}{}
|
||||
)
|
||||
for it = p.next(); it.typ != itemArrayEnd; it = p.next() {
|
||||
if it.typ == itemCommentStart {
|
||||
p.expect(itemText)
|
||||
continue
|
||||
}
|
||||
|
||||
val, typ := p.value(it, true)
|
||||
array = append(array, val)
|
||||
types = append(types, typ)
|
||||
|
||||
// XXX: types isn't used here, we need it to record the accurate type
|
||||
// information.
|
||||
//
|
||||
// Not entirely sure how to best store this; could use "key[0]",
|
||||
// "key[1]" notation, or maybe store it on the Array type?
|
||||
_ = types
|
||||
}
|
||||
return array, tomlArray
|
||||
}
|
||||
|
||||
func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tomlType) {
|
||||
var (
|
||||
hash = make(map[string]interface{})
|
||||
outerContext = p.context
|
||||
outerKey = p.currentKey
|
||||
)
|
||||
|
||||
p.context = append(p.context, p.currentKey)
|
||||
prevContext := p.context
|
||||
p.currentKey = ""
|
||||
|
||||
p.addImplicit(p.context)
|
||||
p.addContext(p.context, parentIsArray)
|
||||
|
||||
/// Loop over all table key/value pairs.
|
||||
for it := p.next(); it.typ != itemInlineTableEnd; it = p.next() {
|
||||
if it.typ == itemCommentStart {
|
||||
p.expect(itemText)
|
||||
continue
|
||||
}
|
||||
|
||||
/// Read all key parts.
|
||||
k := p.nextPos()
|
||||
var key Key
|
||||
for ; k.typ != itemKeyEnd && k.typ != itemEOF; k = p.next() {
|
||||
key = append(key, p.keyString(k))
|
||||
}
|
||||
p.assertEqual(itemKeyEnd, k.typ)
|
||||
|
||||
/// The current key is the last part.
|
||||
p.currentKey = key[len(key)-1]
|
||||
|
||||
/// All the other parts (if any) are the context; need to set each part
|
||||
/// as implicit.
|
||||
context := key[:len(key)-1]
|
||||
for i := range context {
|
||||
p.addImplicitContext(append(p.context, context[i:i+1]...))
|
||||
}
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
|
||||
/// Set the value.
|
||||
val, typ := p.value(p.next(), false)
|
||||
p.set(p.currentKey, val, typ, it.pos)
|
||||
hash[p.currentKey] = val
|
||||
|
||||
/// Restore context.
|
||||
p.context = prevContext
|
||||
}
|
||||
p.context = outerContext
|
||||
p.currentKey = outerKey
|
||||
return hash, tomlHash
|
||||
}
|
||||
|
||||
// numHasLeadingZero checks if this number has leading zeroes, allowing for '0',
|
||||
// +/- signs, and base prefixes.
|
||||
func numHasLeadingZero(s string) bool {
|
||||
if len(s) > 1 && s[0] == '0' && !(s[1] == 'b' || s[1] == 'o' || s[1] == 'x') { // Allow 0b, 0o, 0x
|
||||
return true
|
||||
}
|
||||
if len(s) > 2 && (s[0] == '-' || s[0] == '+') && s[1] == '0' {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// numUnderscoresOK checks whether each underscore in s is surrounded by
|
||||
// characters that are not underscores.
|
||||
func numUnderscoresOK(s string) bool {
|
||||
switch s {
|
||||
case "nan", "+nan", "-nan", "inf", "-inf", "+inf":
|
||||
return true
|
||||
}
|
||||
accept := false
|
||||
for _, r := range s {
|
||||
if r == '_' {
|
||||
if !accept {
|
||||
return false
|
||||
}
|
||||
accept = false
|
||||
continue
|
||||
}
|
||||
accept = true
|
||||
|
||||
// isHexadecimal is a superset of all the permissable characters
|
||||
// surrounding an underscore.
|
||||
accept = isHexadecimal(r)
|
||||
}
|
||||
return accept
|
||||
}
|
||||
|
@ -338,13 +505,12 @@ func numPeriodsOK(s string) bool {
|
|||
return !period
|
||||
}
|
||||
|
||||
// establishContext sets the current context of the parser,
|
||||
// where the context is either a hash or an array of hashes. Which one is
|
||||
// set depends on the value of the `array` parameter.
|
||||
// Set the current context of the parser, where the context is either a hash or
|
||||
// an array of hashes, depending on the value of the `array` parameter.
|
||||
//
|
||||
// Establishing the context also makes sure that the key isn't a duplicate, and
|
||||
// will create implicit hashes automatically.
|
||||
func (p *parser) establishContext(key Key, array bool) {
|
||||
func (p *parser) addContext(key Key, array bool) {
|
||||
var ok bool
|
||||
|
||||
// Always start at the top level and drill down for our context.
|
||||
|
@ -383,7 +549,7 @@ func (p *parser) establishContext(key Key, array bool) {
|
|||
// list of tables for it.
|
||||
k := key[len(key)-1]
|
||||
if _, ok := hashContext[k]; !ok {
|
||||
hashContext[k] = make([]map[string]interface{}, 0, 5)
|
||||
hashContext[k] = make([]map[string]interface{}, 0, 4)
|
||||
}
|
||||
|
||||
// Add a new table. But make sure the key hasn't already been used
|
||||
|
@ -391,8 +557,7 @@ func (p *parser) establishContext(key Key, array bool) {
|
|||
if hash, ok := hashContext[k].([]map[string]interface{}); ok {
|
||||
hashContext[k] = append(hash, make(map[string]interface{}))
|
||||
} else {
|
||||
p.panicf("Key '%s' was already created and cannot be used as "+
|
||||
"an array.", keyContext)
|
||||
p.panicf("Key '%s' was already created and cannot be used as an array.", key)
|
||||
}
|
||||
} else {
|
||||
p.setValue(key[len(key)-1], make(map[string]interface{}))
|
||||
|
@ -400,15 +565,22 @@ func (p *parser) establishContext(key Key, array bool) {
|
|||
p.context = append(p.context, key[len(key)-1])
|
||||
}
|
||||
|
||||
// set calls setValue and setType.
|
||||
func (p *parser) set(key string, val interface{}, typ tomlType, pos Position) {
|
||||
p.setValue(key, val)
|
||||
p.setType(key, typ, pos)
|
||||
}
|
||||
|
||||
// setValue sets the given key to the given value in the current context.
|
||||
// It will make sure that the key hasn't already been defined, account for
|
||||
// implicit key groups.
|
||||
func (p *parser) setValue(key string, value interface{}) {
|
||||
var tmpHash interface{}
|
||||
var ok bool
|
||||
|
||||
hash := p.mapping
|
||||
keyContext := make(Key, 0)
|
||||
var (
|
||||
tmpHash interface{}
|
||||
ok bool
|
||||
hash = p.mapping
|
||||
keyContext Key
|
||||
)
|
||||
for _, k := range p.context {
|
||||
keyContext = append(keyContext, k)
|
||||
if tmpHash, ok = hash[k]; !ok {
|
||||
|
@ -422,24 +594,26 @@ func (p *parser) setValue(key string, value interface{}) {
|
|||
case map[string]interface{}:
|
||||
hash = t
|
||||
default:
|
||||
p.bug("Expected hash to have type 'map[string]interface{}', but "+
|
||||
"it has '%T' instead.", tmpHash)
|
||||
p.panicf("Key '%s' has already been defined.", keyContext)
|
||||
}
|
||||
}
|
||||
keyContext = append(keyContext, key)
|
||||
|
||||
if _, ok := hash[key]; ok {
|
||||
// Typically, if the given key has already been set, then we have
|
||||
// to raise an error since duplicate keys are disallowed. However,
|
||||
// it's possible that a key was previously defined implicitly. In this
|
||||
// case, it is allowed to be redefined concretely. (See the
|
||||
// `tests/valid/implicit-and-explicit-after.toml` test in `toml-test`.)
|
||||
// Normally redefining keys isn't allowed, but the key could have been
|
||||
// defined implicitly and it's allowed to be redefined concretely. (See
|
||||
// the `valid/implicit-and-explicit-after.toml` in toml-test)
|
||||
//
|
||||
// But we have to make sure to stop marking it as an implicit. (So that
|
||||
// another redefinition provokes an error.)
|
||||
//
|
||||
// Note that since it has already been defined (as a hash), we don't
|
||||
// want to overwrite it. So our business is done.
|
||||
if p.isArray(keyContext) {
|
||||
p.removeImplicit(keyContext)
|
||||
hash[key] = value
|
||||
return
|
||||
}
|
||||
if p.isImplicit(keyContext) {
|
||||
p.removeImplicit(keyContext)
|
||||
return
|
||||
|
@ -449,41 +623,37 @@ func (p *parser) setValue(key string, value interface{}) {
|
|||
// key, which is *always* wrong.
|
||||
p.panicf("Key '%s' has already been defined.", keyContext)
|
||||
}
|
||||
|
||||
hash[key] = value
|
||||
}
|
||||
|
||||
// setType sets the type of a particular value at a given key.
|
||||
// It should be called immediately AFTER setValue.
|
||||
// setType sets the type of a particular value at a given key. It should be
|
||||
// called immediately AFTER setValue.
|
||||
//
|
||||
// Note that if `key` is empty, then the type given will be applied to the
|
||||
// current context (which is either a table or an array of tables).
|
||||
func (p *parser) setType(key string, typ tomlType) {
|
||||
func (p *parser) setType(key string, typ tomlType, pos Position) {
|
||||
keyContext := make(Key, 0, len(p.context)+1)
|
||||
for _, k := range p.context {
|
||||
keyContext = append(keyContext, k)
|
||||
}
|
||||
keyContext = append(keyContext, p.context...)
|
||||
if len(key) > 0 { // allow type setting for hashes
|
||||
keyContext = append(keyContext, key)
|
||||
}
|
||||
p.types[keyContext.String()] = typ
|
||||
// Special case to make empty keys ("" = 1) work.
|
||||
// Without it it will set "" rather than `""`.
|
||||
// TODO: why is this needed? And why is this only needed here?
|
||||
if len(keyContext) == 0 {
|
||||
keyContext = Key{""}
|
||||
}
|
||||
p.keyInfo[keyContext.String()] = keyInfo{tomlType: typ, pos: pos}
|
||||
}
|
||||
|
||||
// addImplicit sets the given Key as having been created implicitly.
|
||||
func (p *parser) addImplicit(key Key) {
|
||||
p.implicits[key.String()] = true
|
||||
}
|
||||
|
||||
// removeImplicit stops tagging the given key as having been implicitly
|
||||
// created.
|
||||
func (p *parser) removeImplicit(key Key) {
|
||||
p.implicits[key.String()] = false
|
||||
}
|
||||
|
||||
// isImplicit returns true if the key group pointed to by the key was created
|
||||
// implicitly.
|
||||
func (p *parser) isImplicit(key Key) bool {
|
||||
return p.implicits[key.String()]
|
||||
}
|
||||
// Implicit keys need to be created when tables are implied in "a.b.c.d = 1" and
|
||||
// "[a.b.c]" (the "a", "b", and "c" hashes are never created explicitly).
|
||||
func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} }
|
||||
func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) }
|
||||
func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok }
|
||||
func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray }
|
||||
func (p *parser) addImplicitContext(key Key) { p.addImplicit(key); p.addContext(key, false) }
|
||||
|
||||
// current returns the full key name of the current context.
|
||||
func (p *parser) current() string {
|
||||
|
@ -497,24 +667,67 @@ func (p *parser) current() string {
|
|||
}
|
||||
|
||||
func stripFirstNewline(s string) string {
|
||||
if len(s) == 0 || s[0] != '\n' {
|
||||
return s
|
||||
if len(s) > 0 && s[0] == '\n' {
|
||||
return s[1:]
|
||||
}
|
||||
return s[1:]
|
||||
if len(s) > 1 && s[0] == '\r' && s[1] == '\n' {
|
||||
return s[2:]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func stripEscapedWhitespace(s string) string {
|
||||
esc := strings.Split(s, "\\\n")
|
||||
if len(esc) > 1 {
|
||||
for i := 1; i < len(esc); i++ {
|
||||
esc[i] = strings.TrimLeftFunc(esc[i], unicode.IsSpace)
|
||||
// stripEscapedNewlines removes whitespace after line-ending backslashes in
|
||||
// multiline strings.
|
||||
//
|
||||
// A line-ending backslash is an unescaped \ followed only by whitespace until
|
||||
// the next newline. After a line-ending backslash, all whitespace is removed
|
||||
// until the next non-whitespace character.
|
||||
func (p *parser) stripEscapedNewlines(s string) string {
|
||||
var b strings.Builder
|
||||
var i int
|
||||
for {
|
||||
ix := strings.Index(s[i:], `\`)
|
||||
if ix < 0 {
|
||||
b.WriteString(s)
|
||||
return b.String()
|
||||
}
|
||||
i += ix
|
||||
|
||||
if len(s) > i+1 && s[i+1] == '\\' {
|
||||
// Escaped backslash.
|
||||
i += 2
|
||||
continue
|
||||
}
|
||||
// Scan until the next non-whitespace.
|
||||
j := i + 1
|
||||
whitespaceLoop:
|
||||
for ; j < len(s); j++ {
|
||||
switch s[j] {
|
||||
case ' ', '\t', '\r', '\n':
|
||||
default:
|
||||
break whitespaceLoop
|
||||
}
|
||||
}
|
||||
if j == i+1 {
|
||||
// Not a whitespace escape.
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if !strings.Contains(s[i:j], "\n") {
|
||||
// This is not a line-ending backslash.
|
||||
// (It's a bad escape sequence, but we can let
|
||||
// replaceEscapes catch it.)
|
||||
i++
|
||||
continue
|
||||
}
|
||||
b.WriteString(s[:i])
|
||||
s = s[j:]
|
||||
i = 0
|
||||
}
|
||||
return strings.Join(esc, "")
|
||||
}
|
||||
|
||||
func (p *parser) replaceEscapes(str string) string {
|
||||
var replaced []rune
|
||||
func (p *parser) replaceEscapes(it item, str string) string {
|
||||
replaced := make([]rune, 0, len(str))
|
||||
s := []byte(str)
|
||||
r := 0
|
||||
for r < len(s) {
|
||||
|
@ -532,7 +745,8 @@ func (p *parser) replaceEscapes(str string) string {
|
|||
switch s[r] {
|
||||
default:
|
||||
p.bug("Expected valid escape code after \\, but got %q.", s[r])
|
||||
return ""
|
||||
case ' ', '\t':
|
||||
p.panicItemf(it, "invalid escape: '\\%c'", s[r])
|
||||
case 'b':
|
||||
replaced = append(replaced, rune(0x0008))
|
||||
r += 1
|
||||
|
@ -548,24 +762,35 @@ func (p *parser) replaceEscapes(str string) string {
|
|||
case 'r':
|
||||
replaced = append(replaced, rune(0x000D))
|
||||
r += 1
|
||||
case 'e':
|
||||
if p.tomlNext {
|
||||
replaced = append(replaced, rune(0x001B))
|
||||
r += 1
|
||||
}
|
||||
case '"':
|
||||
replaced = append(replaced, rune(0x0022))
|
||||
r += 1
|
||||
case '\\':
|
||||
replaced = append(replaced, rune(0x005C))
|
||||
r += 1
|
||||
case 'x':
|
||||
if p.tomlNext {
|
||||
escaped := p.asciiEscapeToUnicode(it, s[r+1:r+3])
|
||||
replaced = append(replaced, escaped)
|
||||
r += 3
|
||||
}
|
||||
case 'u':
|
||||
// At this point, we know we have a Unicode escape of the form
|
||||
// `uXXXX` at [r, r+5). (Because the lexer guarantees this
|
||||
// for us.)
|
||||
escaped := p.asciiEscapeToUnicode(s[r+1 : r+5])
|
||||
escaped := p.asciiEscapeToUnicode(it, s[r+1:r+5])
|
||||
replaced = append(replaced, escaped)
|
||||
r += 5
|
||||
case 'U':
|
||||
// At this point, we know we have a Unicode escape of the form
|
||||
// `uXXXX` at [r, r+9). (Because the lexer guarantees this
|
||||
// for us.)
|
||||
escaped := p.asciiEscapeToUnicode(s[r+1 : r+9])
|
||||
escaped := p.asciiEscapeToUnicode(it, s[r+1:r+9])
|
||||
replaced = append(replaced, escaped)
|
||||
r += 9
|
||||
}
|
||||
|
@ -573,20 +798,14 @@ func (p *parser) replaceEscapes(str string) string {
|
|||
return string(replaced)
|
||||
}
|
||||
|
||||
func (p *parser) asciiEscapeToUnicode(bs []byte) rune {
|
||||
func (p *parser) asciiEscapeToUnicode(it item, bs []byte) rune {
|
||||
s := string(bs)
|
||||
hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32)
|
||||
if err != nil {
|
||||
p.bug("Could not parse '%s' as a hexadecimal number, but the "+
|
||||
"lexer claims it's OK: %s", s, err)
|
||||
p.bug("Could not parse '%s' as a hexadecimal number, but the lexer claims it's OK: %s", s, err)
|
||||
}
|
||||
if !utf8.ValidRune(rune(hex)) {
|
||||
p.panicf("Escaped character '\\u%s' is not valid UTF-8.", s)
|
||||
p.panicItemf(it, "Escaped character '\\u%s' is not valid UTF-8.", s)
|
||||
}
|
||||
return rune(hex)
|
||||
}
|
||||
|
||||
func isStringType(ty itemType) bool {
|
||||
return ty == itemString || ty == itemMultilineString ||
|
||||
ty == itemRawString || ty == itemRawMultilineString
|
||||
}
|
||||
|
|
1
vendor/github.com/BurntSushi/toml/session.vim
generated
vendored
1
vendor/github.com/BurntSushi/toml/session.vim
generated
vendored
|
@ -1 +0,0 @@
|
|||
au BufWritePost *.go silent!make tags > /dev/null 2>&1
|
4
vendor/github.com/BurntSushi/toml/type_fields.go
generated
vendored
4
vendor/github.com/BurntSushi/toml/type_fields.go
generated
vendored
|
@ -70,8 +70,8 @@ func typeFields(t reflect.Type) []field {
|
|||
next := []field{{typ: t}}
|
||||
|
||||
// Count of queued names for current level and the next.
|
||||
count := map[reflect.Type]int{}
|
||||
nextCount := map[reflect.Type]int{}
|
||||
var count map[reflect.Type]int
|
||||
var nextCount map[reflect.Type]int
|
||||
|
||||
// Types already visited at an earlier level.
|
||||
visited := map[reflect.Type]bool{}
|
||||
|
|
|
@ -16,7 +16,7 @@ func typeEqual(t1, t2 tomlType) bool {
|
|||
return t1.typeString() == t2.typeString()
|
||||
}
|
||||
|
||||
func typeIsHash(t tomlType) bool {
|
||||
func typeIsTable(t tomlType) bool {
|
||||
return typeEqual(t, tomlHash) || typeEqual(t, tomlArrayHash)
|
||||
}
|
||||
|
||||
|
@ -68,24 +68,3 @@ func (p *parser) typeOfPrimitive(lexItem item) tomlType {
|
|||
p.bug("Cannot infer primitive type of lex item '%s'.", lexItem)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// typeOfArray returns a tomlType for an array given a list of types of its
|
||||
// values.
|
||||
//
|
||||
// In the current spec, if an array is homogeneous, then its type is always
|
||||
// "Array". If the array is not homogeneous, an error is generated.
|
||||
func (p *parser) typeOfArray(types []tomlType) tomlType {
|
||||
// Empty arrays are cool.
|
||||
if len(types) == 0 {
|
||||
return tomlArray
|
||||
}
|
||||
|
||||
theType := types[0]
|
||||
for _, t := range types[1:] {
|
||||
if !typeEqual(theType, t) {
|
||||
p.panicf("Array contains values of type '%s' and '%s', but "+
|
||||
"arrays must be homogeneous.", theType, t)
|
||||
}
|
||||
}
|
||||
return tomlArray
|
||||
}
|
1
vendor/github.com/andygrunwald/go-jira/.gitignore
generated
vendored
1
vendor/github.com/andygrunwald/go-jira/.gitignore
generated
vendored
|
@ -27,3 +27,4 @@ _testmain.go
|
|||
*.prof
|
||||
*.iml
|
||||
.idea
|
||||
.DS_Store
|
20
vendor/github.com/andygrunwald/go-jira/.travis.yml
generated
vendored
20
vendor/github.com/andygrunwald/go-jira/.travis.yml
generated
vendored
|
@ -1,20 +0,0 @@
|
|||
language: go
|
||||
|
||||
sudo: false
|
||||
|
||||
go:
|
||||
- "1.9.x"
|
||||
- "1.10.x"
|
||||
- "1.11.x"
|
||||
- "1.12.x"
|
||||
- "1.13.x"
|
||||
|
||||
before_install:
|
||||
- go get -t ./...
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: 1.13.x
|
||||
|
||||
script:
|
||||
- GOMAXPROCS=4 GORACE="halt_on_error=1" go test -race -v ./...
|
29
vendor/github.com/andygrunwald/go-jira/CHANGELOG.md
generated
vendored
29
vendor/github.com/andygrunwald/go-jira/CHANGELOG.md
generated
vendored
|
@ -2,6 +2,32 @@
|
|||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
## [1.13.0](https://github.com/andygrunwald/go-jira/compare/v1.11.1...v1.13.0) (2020-10-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add AddRemoteLink method ([f200e15](https://github.com/andygrunwald/go-jira/commit/f200e158b997a303db081cbbc5a9d8ad5d89566d)), closes [/developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2](https://github.com/andygrunwald//developer.atlassian.com/cloud/jira/platform/rest/v2//issues/api-rest-api-2)
|
||||
* Add Names support on Issue struct ([#278](https://github.com/andygrunwald/go-jira/issues/278)) ([1fc10e0](https://github.com/andygrunwald/go-jira/commit/1fc10e0606784f745673ccc4d8d706c36f385a7a))
|
||||
* Extend Makefile for more source code quality targets ([5e52236](https://github.com/andygrunwald/go-jira/commit/5e5223631a29d10a13e598318a6abe47384e2982))
|
||||
* **context:** Add support for context package ([e1f4265](https://github.com/andygrunwald/go-jira/commit/e1f4265e2b467b938fe0c095caf6d36f3136d2ff))
|
||||
* **issues:** Add GetEditMeta on issue ([a783764](https://github.com/andygrunwald/go-jira/commit/a783764b52dc890773658ddd0483a9d0393e385d)), closes [/docs.atlassian.com/DAC/rest/jira/6.1.html#d2e1364](https://github.com/andygrunwald//docs.atlassian.com/DAC/rest/jira/6.1.html/issues/d2e1364)
|
||||
* **IssueService:** allow empty JQL ([#268](https://github.com/andygrunwald/go-jira/issues/268)) ([4b91cf2](https://github.com/andygrunwald/go-jira/commit/4b91cf2b135355de7ecee41727c3e65f4e7067bc))
|
||||
* **project:** Add cronjob to check for stale issues ([#287](https://github.com/andygrunwald/go-jira/issues/287)) ([2096b04](https://github.com/andygrunwald/go-jira/commit/2096b04e52b434c1fb1c841bab487a94674a271e))
|
||||
* **project:** Add GitHub Actions testing workflow ([#289](https://github.com/andygrunwald/go-jira/issues/289)) ([80c0282](https://github.com/andygrunwald/go-jira/commit/80c02828ca9e4eb0e4a1877275baae14d330a2d9)), closes [#290](https://github.com/andygrunwald/go-jira/issues/290)
|
||||
* **project:** Add workflow to greet new contributors ([#288](https://github.com/andygrunwald/go-jira/issues/288)) ([c357b61](https://github.com/andygrunwald/go-jira/commit/c357b61a40f62a919ebd94a555390958f99c8db7))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* change millisecond time format ([8c77107](https://github.com/andygrunwald/go-jira/commit/8c77107df3757c4ec5eae6e9d7c018618e708bfa))
|
||||
* paging with load balancer going to endless loop ([19d3fc0](https://github.com/andygrunwald/go-jira/commit/19d3fc0aecde547ffe1ab547c5ffb6c7972d387c)), closes [#260](https://github.com/andygrunwald/go-jira/issues/260)
|
||||
* **issue:** IssueService.Search() with a not empty JQL triggers 400 bad request ([#292](https://github.com/andygrunwald/go-jira/issues/292)) ([8b64c7f](https://github.com/andygrunwald/go-jira/commit/8b64c7f005fbceb11fa43a7aff3de61eb3166fca)), closes [#291](https://github.com/andygrunwald/go-jira/issues/291)
|
||||
* **IssueService.GetWatchers:** UserService.GetByAccountID support accountId params ([436469b](https://github.com/andygrunwald/go-jira/commit/436469b62d4d62037f380b38c918a13f4a5f0ab2))
|
||||
* **product:** Make product naming consistent, rename JIRA to Jira ([#286](https://github.com/andygrunwald/go-jira/issues/286)) ([146229d](https://github.com/andygrunwald/go-jira/commit/146229d2ab58a3fb128ddc8dcbe03aff72e20857)), closes [#284](https://github.com/andygrunwald/go-jira/issues/284)
|
||||
* **tests:** Fix TestIssueService_PostAttachment unit test ([f6b1dca](https://github.com/andygrunwald/go-jira/commit/f6b1dcafcfdd8fe69f842b1053c4030da6c97c7f))
|
||||
* removing the use of username field in searching for users ([#297](https://github.com/andygrunwald/go-jira/issues/297)) ([f50cb07](https://github.com/andygrunwald/go-jira/commit/f50cb07b297d79138b13e5ab49ea33965d32f5c1))
|
||||
|
||||
## [1.12.0](https://github.com/andygrunwald/go-jira/compare/v1.11.1...v1.12.0) (2019-12-14)
|
||||
|
||||
|
||||
|
@ -76,6 +102,3 @@ All notable changes to this project will be documented in this file. See [standa
|
|||
* Add ResolutionService to retrieve resolutions ([fb1ce22](https://github.com/andygrunwald/go-jira/commit/fb1ce22))
|
||||
* Add status category constants ([6223ddd](https://github.com/andygrunwald/go-jira/commit/6223ddd))
|
||||
* Add StatusCategory GetList ([049a756](https://github.com/andygrunwald/go-jira/commit/049a756))
|
||||
|
||||
|
||||
|
||||
|
|
27
vendor/github.com/andygrunwald/go-jira/Makefile
generated
vendored
27
vendor/github.com/andygrunwald/go-jira/Makefile
generated
vendored
|
@ -1,2 +1,25 @@
|
|||
test:
|
||||
go test -v ./...
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
.PHONY: help
|
||||
help: ## Outputs the help.
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: test
|
||||
test: ## Runs all unit, integration and example tests.
|
||||
go test -race -v ./...
|
||||
|
||||
.PHONY: vet
|
||||
vet: ## Runs go vet (to detect suspicious constructs).
|
||||
go vet ./...
|
||||
|
||||
.PHONY: fmt
|
||||
fmt: ## Runs go fmt (to check for go coding guidelines).
|
||||
gofmt -d -s .
|
||||
|
||||
.PHONY: staticcheck
|
||||
staticcheck: ## Runs static analysis to prevend bugs, foster code simplicity, performance and editor integration.
|
||||
go install honnef.co/go/tools/cmd/staticcheck@2022.1
|
||||
staticcheck ./...
|
||||
|
||||
.PHONY: all
|
||||
all: test vet fmt staticcheck ## Runs all source code quality targets (like test, vet, fmt, staticcheck)
|
||||
|
|
15
vendor/github.com/andygrunwald/go-jira/PULL_REQUEST_TEMPLATE.md
generated
vendored
15
vendor/github.com/andygrunwald/go-jira/PULL_REQUEST_TEMPLATE.md
generated
vendored
|
@ -1,15 +0,0 @@
|
|||
# PR Description
|
||||
|
||||
_What does this fix or add?_
|
||||
|
||||
# Checklist
|
||||
|
||||
* [ ] Tests added
|
||||
* [ ] Good Path
|
||||
* [ ] Error Path
|
||||
* [ ] Commits follow conventions described here:
|
||||
* [ ] [https://conventionalcommits.org/en/v1.0.0-beta.4/#summary](https://conventionalcommits.org/en/v1.0.0-beta.4/#summary)
|
||||
* [ ] [https://chris.beams.io/posts/git-commit/#seven-rules](https://chris.beams.io/posts/git-commit/#seven-rules)
|
||||
* [ ] Commits are squashed such that
|
||||
* [ ] There is 1 commit per isolated change
|
||||
* [ ] I've not made extraneous commits/changes that are unrelated to my change.
|
97
vendor/github.com/andygrunwald/go-jira/README.md
generated
vendored
97
vendor/github.com/andygrunwald/go-jira/README.md
generated
vendored
|
@ -1,26 +1,29 @@
|
|||
# go-jira
|
||||
|
||||
[](https://godoc.org/github.com/andygrunwald/go-jira)
|
||||
[](https://travis-ci.org/andygrunwald/go-jira)
|
||||
[](https://github.com/andygrunwald/go-jira/actions/workflows/testing.yml)
|
||||
[](https://goreportcard.com/report/github.com/andygrunwald/go-jira)
|
||||
|
||||
[Go](https://golang.org/) client library for [Atlassian JIRA](https://www.atlassian.com/software/jira).
|
||||
[Go](https://golang.org/) client library for [Atlassian Jira](https://www.atlassian.com/software/jira).
|
||||
|
||||

|
||||

|
||||
|
||||
## Features
|
||||
|
||||
* Authentication (HTTP Basic, OAuth, Session Cookie)
|
||||
* Create and retrieve issues
|
||||
* Create and retrieve issue transitions (status updates)
|
||||
* Call every API endpoint of the JIRA, even if it is not directly implemented in this library
|
||||
* Call every API endpoint of the Jira, even if it is not directly implemented in this library
|
||||
|
||||
This package is not JIRA API complete (yet), but you can call every API endpoint you want. See [Call a not implemented API endpoint](#call-a-not-implemented-api-endpoint) how to do this. For all possible API endpoints of JIRA have a look at [latest JIRA REST API documentation](https://docs.atlassian.com/jira/REST/latest/).
|
||||
This package is not Jira API complete (yet), but you can call every API endpoint you want. See [Call a not implemented API endpoint](#call-a-not-implemented-api-endpoint) how to do this. For all possible API endpoints of Jira have a look at [latest Jira REST API documentation](https://docs.atlassian.com/jira/REST/latest/).
|
||||
|
||||
## Requirements
|
||||
|
||||
* Go >= 1.8
|
||||
* JIRA v6.3.4 & v7.1.2.
|
||||
* Go >= 1.14
|
||||
* Jira v6.3.4 & v7.1.2.
|
||||
|
||||
Note that we also run our tests against 1.13, though only the last two versions
|
||||
of Go are officially supported.
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -52,7 +55,7 @@ go test -v ./...
|
|||
|
||||
Please have a look at the [GoDoc documentation](https://godoc.org/github.com/andygrunwald/go-jira) for a detailed API description.
|
||||
|
||||
The [latest JIRA REST API documentation](https://docs.atlassian.com/jira/REST/latest/) was the base document for this package.
|
||||
The [latest Jira REST API documentation](https://docs.atlassian.com/jira/REST/latest/) was the base document for this package.
|
||||
|
||||
## Examples
|
||||
|
||||
|
@ -68,7 +71,7 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/andygrunwald/go-jira"
|
||||
jira "github.com/andygrunwald/go-jira"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -92,9 +95,11 @@ an `http.Client`. That client can then be passed into the `NewClient` function
|
|||
|
||||
For convenience, capability for basic and cookie-based authentication is included in the main library.
|
||||
|
||||
#### Basic auth example
|
||||
#### Token (Jira on Atlassian Cloud)
|
||||
|
||||
A more thorough, [runnable example](examples/basicauth/main.go) is provided in the examples directory. **It's worth noting that using passwords in basic auth is now deprecated and will be removed.** Jira gives you the ability to [create tokens now.](https://confluence.atlassian.com/cloud/api-tokens-938839638.html)
|
||||
Token-based authentication uses the basic authentication scheme, with a user-generated API token in place of a user's password. You can generate a token for your user [here](https://id.atlassian.com/manage-profile/security/api-tokens). Additional information about Atlassian Cloud API tokens can be found [here](https://confluence.atlassian.com/cloud/api-tokens-938839638.html).
|
||||
|
||||
A more thorough, [runnable example](examples/basicauth/main.go) is provided in the examples directory.
|
||||
|
||||
```go
|
||||
func main() {
|
||||
|
@ -111,14 +116,15 @@ func main() {
|
|||
}
|
||||
```
|
||||
|
||||
#### Authenticate with session cookie [DEPRECATED]
|
||||
#### Basic (self-hosted Jira)
|
||||
|
||||
JIRA [deprecated this authentication method.](https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-basic-auth-and-cookie-based-auth/) It's not longer available for use.
|
||||
Password-based API authentication works for self-hosted Jira **only**, and has been [deprecated for users of Atlassian Cloud](https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-basic-auth-and-cookie-based-auth/).
|
||||
|
||||
The above token authentication example may be used, substituting a user's password for a generated token.
|
||||
|
||||
#### Authenticate with OAuth
|
||||
|
||||
If you want to connect via OAuth to your JIRA Cloud instance checkout the [example of using OAuth authentication with JIRA in Go](https://gist.github.com/Lupus/edafe9a7c5c6b13407293d795442fe67) by [@Lupus](https://github.com/Lupus).
|
||||
If you want to connect via OAuth to your Jira Cloud instance checkout the [example of using OAuth authentication with Jira in Go](https://gist.github.com/Lupus/edafe9a7c5c6b13407293d795442fe67) by [@Lupus](https://github.com/Lupus).
|
||||
|
||||
For more details have a look at the [issue #56](https://github.com/andygrunwald/go-jira/issues/56).
|
||||
|
||||
|
@ -173,11 +179,62 @@ func main() {
|
|||
}
|
||||
```
|
||||
|
||||
### Change an issue status
|
||||
|
||||
This is how one can change an issue status. In this example, we change the issue from "To Do" to "In Progress."
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/andygrunwald/go-jira"
|
||||
)
|
||||
|
||||
func main() {
|
||||
base := "https://my.jira.com"
|
||||
tp := jira.BasicAuthTransport{
|
||||
Username: "username",
|
||||
Password: "token",
|
||||
}
|
||||
|
||||
jiraClient, err := jira.NewClient(tp.Client(), base)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
issue, _, _ := jiraClient.Issue.Get("FART-1", nil)
|
||||
currentStatus := issue.Fields.Status.Name
|
||||
fmt.Printf("Current status: %s\n", currentStatus)
|
||||
|
||||
var transitionID string
|
||||
possibleTransitions, _, _ := jiraClient.Issue.GetTransitions("FART-1")
|
||||
for _, v := range possibleTransitions {
|
||||
if v.Name == "In Progress" {
|
||||
transitionID = v.ID
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
jiraClient.Issue.DoTransition("FART-1", transitionID)
|
||||
issue, _, _ = jiraClient.Issue.Get(testIssueID, nil)
|
||||
fmt.Printf("Status after transition: %+v\n", issue.Fields.Status.Name)
|
||||
}
|
||||
```
|
||||
### Get all the issues for JQL with Pagination
|
||||
Jira API has limit on maxResults it can return. You may have a usecase where you need to get all issues for given JQL.
|
||||
This example shows reference implementation of GetAllIssues function which does pagination on Jira API to get all the issues for given JQL
|
||||
|
||||
please look at [Pagination Example](https://github.com/andygrunwald/go-jira/blob/master/examples/pagination/main.go)
|
||||
|
||||
|
||||
|
||||
|
||||
### Call a not implemented API endpoint
|
||||
|
||||
Not all API endpoints of the JIRA API are implemented into *go-jira*.
|
||||
Not all API endpoints of the Jira API are implemented into *go-jira*.
|
||||
But you can call them anyway:
|
||||
Lets get all public projects of [Atlassian`s JIRA instance](https://jira.atlassian.com/).
|
||||
Lets get all public projects of [Atlassian`s Jira instance](https://jira.atlassian.com/).
|
||||
|
||||
```go
|
||||
package main
|
||||
|
@ -209,7 +266,7 @@ func main() {
|
|||
|
||||
// ...
|
||||
// BAM: Bamboo
|
||||
// BAMJ: Bamboo JIRA Plugin
|
||||
// BAMJ: Bamboo Jira Plugin
|
||||
// CLOV: Clover
|
||||
// CONF: Confluence
|
||||
// ...
|
||||
|
@ -218,7 +275,7 @@ func main() {
|
|||
|
||||
## Implementations
|
||||
|
||||
* [andygrunwald/jitic](https://github.com/andygrunwald/jitic) - The JIRA Ticket Checker
|
||||
* [andygrunwald/jitic](https://github.com/andygrunwald/jitic) - The Jira Ticket Checker
|
||||
|
||||
## Code structure
|
||||
|
||||
|
@ -226,7 +283,7 @@ The code structure of this package was inspired by [google/go-github](https://gi
|
|||
|
||||
There is one main part (the client).
|
||||
Based on this main client the other endpoints, like Issues or Authentication are extracted in services. E.g. `IssueService` or `AuthenticationService`.
|
||||
These services own a responsibility of the single endpoints / usecases of JIRA.
|
||||
These services own a responsibility of the single endpoints / usecases of Jira.
|
||||
|
||||
## Contribution
|
||||
|
||||
|
@ -258,7 +315,7 @@ You can read more about them at https://developer.atlassian.com/blog/2016/04/clo
|
|||
|
||||
## Releasing
|
||||
|
||||
Install `standard-version`
|
||||
Install [standard-version](https://github.com/conventional-changelog/standard-version)
|
||||
```bash
|
||||
npm i -g standard-version
|
||||
```
|
||||
|
|
89
vendor/github.com/andygrunwald/go-jira/authentication.go
generated
vendored
89
vendor/github.com/andygrunwald/go-jira/authentication.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -14,9 +15,9 @@ const (
|
|||
authTypeSession = 2
|
||||
)
|
||||
|
||||
// AuthenticationService handles authentication for the JIRA instance / API.
|
||||
// AuthenticationService handles authentication for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#authentication
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#authentication
|
||||
type AuthenticationService struct {
|
||||
client *Client
|
||||
|
||||
|
@ -30,7 +31,7 @@ type AuthenticationService struct {
|
|||
password string
|
||||
}
|
||||
|
||||
// Session represents a Session JSON response by the JIRA API.
|
||||
// Session represents a Session JSON response by the Jira API.
|
||||
type Session struct {
|
||||
Self string `json:"self,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
|
@ -47,16 +48,16 @@ type Session struct {
|
|||
Cookies []*http.Cookie
|
||||
}
|
||||
|
||||
// AcquireSessionCookie creates a new session for a user in JIRA.
|
||||
// Once a session has been successfully created it can be used to access any of JIRA's remote APIs and also the web UI by passing the appropriate HTTP Cookie header.
|
||||
// AcquireSessionCookieWithContext creates a new session for a user in Jira.
|
||||
// Once a session has been successfully created it can be used to access any of Jira's remote APIs and also the web UI by passing the appropriate HTTP Cookie header.
|
||||
// The header will by automatically applied to every API request.
|
||||
// Note that it is generally preferrable to use HTTP BASIC authentication with the REST API.
|
||||
// However, this resource may be used to mimic the behaviour of JIRA's log-in page (e.g. to display log-in errors to a user).
|
||||
// However, this resource may be used to mimic the behaviour of Jira's log-in page (e.g. to display log-in errors to a user).
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
|
||||
//
|
||||
// Deprecated: Use CookieAuthTransport instead
|
||||
func (s *AuthenticationService) AcquireSessionCookie(username, password string) (bool, error) {
|
||||
func (s *AuthenticationService) AcquireSessionCookieWithContext(ctx context.Context, username, password string) (bool, error) {
|
||||
apiEndpoint := "rest/auth/1/session"
|
||||
body := struct {
|
||||
Username string `json:"username"`
|
||||
|
@ -66,7 +67,7 @@ func (s *AuthenticationService) AcquireSessionCookie(username, password string)
|
|||
password,
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("POST", apiEndpoint, body)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, body)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -79,10 +80,10 @@ func (s *AuthenticationService) AcquireSessionCookie(username, password string)
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Auth at JIRA instance failed (HTTP(S) request). %s", err)
|
||||
return false, fmt.Errorf("auth at Jira instance failed (HTTP(S) request). %s", err)
|
||||
}
|
||||
if resp != nil && resp.StatusCode != 200 {
|
||||
return false, fmt.Errorf("Auth at JIRA instance failed (HTTP(S) request). Status code: %d", resp.StatusCode)
|
||||
return false, fmt.Errorf("auth at Jira instance failed (HTTP(S) request). Status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
s.client.session = session
|
||||
|
@ -91,7 +92,14 @@ func (s *AuthenticationService) AcquireSessionCookie(username, password string)
|
|||
return true, nil
|
||||
}
|
||||
|
||||
// SetBasicAuth sets username and password for the basic auth against the JIRA instance.
|
||||
// AcquireSessionCookie wraps AcquireSessionCookieWithContext using the background context.
|
||||
//
|
||||
// Deprecated: Use CookieAuthTransport instead
|
||||
func (s *AuthenticationService) AcquireSessionCookie(username, password string) (bool, error) {
|
||||
return s.AcquireSessionCookieWithContext(context.Background(), username, password)
|
||||
}
|
||||
|
||||
// SetBasicAuth sets username and password for the basic auth against the Jira instance.
|
||||
//
|
||||
// Deprecated: Use BasicAuthTransport instead
|
||||
func (s *AuthenticationService) SetBasicAuth(username, password string) {
|
||||
|
@ -100,7 +108,7 @@ func (s *AuthenticationService) SetBasicAuth(username, password string) {
|
|||
s.authType = authTypeBasic
|
||||
}
|
||||
|
||||
// Authenticated reports if the current Client has authentication details for JIRA
|
||||
// Authenticated reports if the current Client has authentication details for Jira
|
||||
func (s *AuthenticationService) Authenticated() bool {
|
||||
if s != nil {
|
||||
if s.authType == authTypeSession {
|
||||
|
@ -113,29 +121,30 @@ func (s *AuthenticationService) Authenticated() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Logout logs out the current user that has been authenticated and the session in the client is destroyed.
|
||||
// LogoutWithContext logs out the current user that has been authenticated and the session in the client is destroyed.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
|
||||
//
|
||||
// Deprecated: Use CookieAuthTransport to create base client. Logging out is as simple as not using the
|
||||
// client anymore
|
||||
func (s *AuthenticationService) Logout() error {
|
||||
func (s *AuthenticationService) LogoutWithContext(ctx context.Context) error {
|
||||
if s.authType != authTypeSession || s.client.session == nil {
|
||||
return fmt.Errorf("no user is authenticated")
|
||||
}
|
||||
|
||||
apiEndpoint := "rest/auth/1/session"
|
||||
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Creating the request to log the user out failed : %s", err)
|
||||
return fmt.Errorf("creating the request to log the user out failed : %s", err)
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error sending the logout request: %s", err)
|
||||
return fmt.Errorf("error sending the logout request: %s", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 204 {
|
||||
return fmt.Errorf("The logout was unsuccessful with status %d", resp.StatusCode)
|
||||
return fmt.Errorf("the logout was unsuccessful with status %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// If logout successful, delete session
|
||||
|
@ -145,43 +154,55 @@ func (s *AuthenticationService) Logout() error {
|
|||
|
||||
}
|
||||
|
||||
// GetCurrentUser gets the details of the current user.
|
||||
// Logout wraps LogoutWithContext using the background context.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
|
||||
func (s *AuthenticationService) GetCurrentUser() (*Session, error) {
|
||||
// Deprecated: Use CookieAuthTransport to create base client. Logging out is as simple as not using the
|
||||
// client anymore
|
||||
func (s *AuthenticationService) Logout() error {
|
||||
return s.LogoutWithContext(context.Background())
|
||||
}
|
||||
|
||||
// GetCurrentUserWithContext gets the details of the current user.
|
||||
//
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
|
||||
func (s *AuthenticationService) GetCurrentUserWithContext(ctx context.Context) (*Session, error) {
|
||||
if s == nil {
|
||||
return nil, fmt.Errorf("AUthenticaiton Service is not instantiated")
|
||||
return nil, fmt.Errorf("authentication Service is not instantiated")
|
||||
}
|
||||
if s.authType != authTypeSession || s.client.session == nil {
|
||||
return nil, fmt.Errorf("No user is authenticated yet")
|
||||
return nil, fmt.Errorf("no user is authenticated yet")
|
||||
}
|
||||
|
||||
apiEndpoint := "rest/auth/1/session"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not create request for getting user info : %s", err)
|
||||
return nil, fmt.Errorf("could not create request for getting user info : %s", err)
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error sending request to get user info : %s", err)
|
||||
return nil, fmt.Errorf("error sending request to get user info : %s", err)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("Getting user info failed with status : %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("getting user info failed with status : %d", resp.StatusCode)
|
||||
}
|
||||
ret := new(Session)
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Couldn't read body from the response : %s", err)
|
||||
return nil, fmt.Errorf("couldn't read body from the response : %s", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(data, &ret)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not unmarshall received user info : %s", err)
|
||||
return nil, fmt.Errorf("could not unmarshall received user info : %s", err)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// GetCurrentUser wraps GetCurrentUserWithContext using the background context.
|
||||
func (s *AuthenticationService) GetCurrentUser() (*Session, error) {
|
||||
return s.GetCurrentUserWithContext(context.Background())
|
||||
}
|
||||
|
|
100
vendor/github.com/andygrunwald/go-jira/board.go
generated
vendored
100
vendor/github.com/andygrunwald/go-jira/board.go
generated
vendored
|
@ -1,14 +1,15 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BoardService handles Agile Boards for the JIRA instance / API.
|
||||
// BoardService handles Agile Boards for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/server/
|
||||
// Jira API docs: https://docs.atlassian.com/jira-software/REST/server/
|
||||
type BoardService struct {
|
||||
client *Client
|
||||
}
|
||||
|
@ -22,7 +23,7 @@ type BoardsList struct {
|
|||
Values []Board `json:"values" structs:"values"`
|
||||
}
|
||||
|
||||
// Board represents a JIRA agile board
|
||||
// Board represents a Jira agile board
|
||||
type Board struct {
|
||||
ID int `json:"id,omitempty" structs:"id,omitempty"`
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
|
@ -62,7 +63,7 @@ type SprintsList struct {
|
|||
Values []Sprint `json:"values" structs:"values"`
|
||||
}
|
||||
|
||||
// Sprint represents a sprint on JIRA agile board
|
||||
// Sprint represents a sprint on Jira agile board
|
||||
type Sprint struct {
|
||||
ID int `json:"id" structs:"id"`
|
||||
Name string `json:"name" structs:"name"`
|
||||
|
@ -116,6 +117,8 @@ type BoardConfigurationColumnConfig struct {
|
|||
type BoardConfigurationColumn struct {
|
||||
Name string `json:"name"`
|
||||
Status []BoardConfigurationColumnStatus `json:"statuses"`
|
||||
Min int `json:"min,omitempty"`
|
||||
Max int `json:"max,omitempty"`
|
||||
}
|
||||
|
||||
// BoardConfigurationColumnStatus represents a status in the column configuration
|
||||
|
@ -124,16 +127,16 @@ type BoardConfigurationColumnStatus struct {
|
|||
Self string `json:"self"`
|
||||
}
|
||||
|
||||
// GetAllBoards will returns all boards. This only includes boards that the user has permission to view.
|
||||
// GetAllBoardsWithContext will returns all boards. This only includes boards that the user has permission to view.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getAllBoards
|
||||
func (s *BoardService) GetAllBoards(opt *BoardListOptions) (*BoardsList, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getAllBoards
|
||||
func (s *BoardService) GetAllBoardsWithContext(ctx context.Context, opt *BoardListOptions) (*BoardsList, *Response, error) {
|
||||
apiEndpoint := "rest/agile/1.0/board"
|
||||
url, err := addOptions(apiEndpoint, opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := s.client.NewRequest("GET", url, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -148,13 +151,18 @@ func (s *BoardService) GetAllBoards(opt *BoardListOptions) (*BoardsList, *Respon
|
|||
return boards, resp, err
|
||||
}
|
||||
|
||||
// GetBoard will returns the board for the given boardID.
|
||||
// GetAllBoards wraps GetAllBoardsWithContext using the background context.
|
||||
func (s *BoardService) GetAllBoards(opt *BoardListOptions) (*BoardsList, *Response, error) {
|
||||
return s.GetAllBoardsWithContext(context.Background(), opt)
|
||||
}
|
||||
|
||||
// GetBoardWithContext will returns the board for the given boardID.
|
||||
// This board will only be returned if the user has permission to view it.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getBoard
|
||||
func (s *BoardService) GetBoard(boardID int) (*Board, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getBoard
|
||||
func (s *BoardService) GetBoardWithContext(ctx context.Context, boardID int) (*Board, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%v", boardID)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -169,17 +177,22 @@ func (s *BoardService) GetBoard(boardID int) (*Board, *Response, error) {
|
|||
return board, resp, nil
|
||||
}
|
||||
|
||||
// CreateBoard creates a new board. Board name, type and filter Id is required.
|
||||
// GetBoard wraps GetBoardWithContext using the background context.
|
||||
func (s *BoardService) GetBoard(boardID int) (*Board, *Response, error) {
|
||||
return s.GetBoardWithContext(context.Background(), boardID)
|
||||
}
|
||||
|
||||
// CreateBoardWithContext creates a new board. Board name, type and filter Id is required.
|
||||
// name - Must be less than 255 characters.
|
||||
// type - Valid values: scrum, kanban
|
||||
// filterId - Id of a filter that the user has permissions to view.
|
||||
// Note, if the user does not have the 'Create shared objects' permission and tries to create a shared board, a private
|
||||
// board will be created instead (remember that board sharing depends on the filter sharing).
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-createBoard
|
||||
func (s *BoardService) CreateBoard(board *Board) (*Board, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-createBoard
|
||||
func (s *BoardService) CreateBoardWithContext(ctx context.Context, board *Board) (*Board, *Response, error) {
|
||||
apiEndpoint := "rest/agile/1.0/board"
|
||||
req, err := s.client.NewRequest("POST", apiEndpoint, board)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, board)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -194,12 +207,18 @@ func (s *BoardService) CreateBoard(board *Board) (*Board, *Response, error) {
|
|||
return responseBoard, resp, nil
|
||||
}
|
||||
|
||||
// DeleteBoard will delete an agile board.
|
||||
// CreateBoard wraps CreateBoardWithContext using the background context.
|
||||
func (s *BoardService) CreateBoard(board *Board) (*Board, *Response, error) {
|
||||
return s.CreateBoardWithContext(context.Background(), board)
|
||||
}
|
||||
|
||||
// DeleteBoardWithContext will delete an agile board.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-deleteBoard
|
||||
func (s *BoardService) DeleteBoard(boardID int) (*Board, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-deleteBoard
|
||||
// Caller must close resp.Body
|
||||
func (s *BoardService) DeleteBoardWithContext(ctx context.Context, boardID int) (*Board, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%v", boardID)
|
||||
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -211,11 +230,17 @@ func (s *BoardService) DeleteBoard(boardID int) (*Board, *Response, error) {
|
|||
return nil, resp, err
|
||||
}
|
||||
|
||||
// GetAllSprints will return all sprints from a board, for a given board Id.
|
||||
// DeleteBoard wraps DeleteBoardWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *BoardService) DeleteBoard(boardID int) (*Board, *Response, error) {
|
||||
return s.DeleteBoardWithContext(context.Background(), boardID)
|
||||
}
|
||||
|
||||
// GetAllSprintsWithContext will return all sprints from a board, for a given board Id.
|
||||
// This only includes sprints that the user has permission to view.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint
|
||||
func (s *BoardService) GetAllSprints(boardID string) ([]Sprint, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint
|
||||
func (s *BoardService) GetAllSprintsWithContext(ctx context.Context, boardID string) ([]Sprint, *Response, error) {
|
||||
id, err := strconv.Atoi(boardID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -229,17 +254,22 @@ func (s *BoardService) GetAllSprints(boardID string) ([]Sprint, *Response, error
|
|||
return result.Values, response, nil
|
||||
}
|
||||
|
||||
// GetAllSprintsWithOptions will return sprints from a board, for a given board Id and filtering options
|
||||
// GetAllSprints wraps GetAllSprintsWithContext using the background context.
|
||||
func (s *BoardService) GetAllSprints(boardID string) ([]Sprint, *Response, error) {
|
||||
return s.GetAllSprintsWithContext(context.Background(), boardID)
|
||||
}
|
||||
|
||||
// GetAllSprintsWithOptionsWithContext will return sprints from a board, for a given board Id and filtering options
|
||||
// This only includes sprints that the user has permission to view.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint
|
||||
func (s *BoardService) GetAllSprintsWithOptions(boardID int, options *GetAllSprintsOptions) (*SprintsList, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint
|
||||
func (s *BoardService) GetAllSprintsWithOptionsWithContext(ctx context.Context, boardID int, options *GetAllSprintsOptions) (*SprintsList, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/sprint", boardID)
|
||||
url, err := addOptions(apiEndpoint, options)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := s.client.NewRequest("GET", url, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -253,12 +283,17 @@ func (s *BoardService) GetAllSprintsWithOptions(boardID int, options *GetAllSpri
|
|||
return result, resp, err
|
||||
}
|
||||
|
||||
// GetBoardConfiguration will return a board configuration for a given board Id
|
||||
// GetAllSprintsWithOptions wraps GetAllSprintsWithOptionsWithContext using the background context.
|
||||
func (s *BoardService) GetAllSprintsWithOptions(boardID int, options *GetAllSprintsOptions) (*SprintsList, *Response, error) {
|
||||
return s.GetAllSprintsWithOptionsWithContext(context.Background(), boardID, options)
|
||||
}
|
||||
|
||||
// GetBoardConfigurationWithContext will return a board configuration for a given board Id
|
||||
// Jira API docs:https://developer.atlassian.com/cloud/jira/software/rest/#api-rest-agile-1-0-board-boardId-configuration-get
|
||||
func (s *BoardService) GetBoardConfiguration(boardID int) (*BoardConfiguration, *Response, error) {
|
||||
func (s *BoardService) GetBoardConfigurationWithContext(ctx context.Context, boardID int) (*BoardConfiguration, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/configuration", boardID)
|
||||
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -273,3 +308,8 @@ func (s *BoardService) GetBoardConfiguration(boardID int) (*BoardConfiguration,
|
|||
return result, resp, err
|
||||
|
||||
}
|
||||
|
||||
// GetBoardConfiguration wraps GetBoardConfigurationWithContext using the background context.
|
||||
func (s *BoardService) GetBoardConfiguration(boardID int) (*BoardConfiguration, *Response, error) {
|
||||
return s.GetBoardConfigurationWithContext(context.Background(), boardID)
|
||||
}
|
||||
|
|
20
vendor/github.com/andygrunwald/go-jira/component.go
generated
vendored
20
vendor/github.com/andygrunwald/go-jira/component.go
generated
vendored
|
@ -1,13 +1,14 @@
|
|||
package jira
|
||||
|
||||
// ComponentService handles components for the JIRA instance / API.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/7.10.1/#api/2/component
|
||||
import "context"
|
||||
|
||||
// ComponentService handles components for the Jira instance / API.//
|
||||
// Jira API docs: https://docs.atlassian.com/software/jira/docs/api/REST/7.10.1/#api/2/component
|
||||
type ComponentService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// CreateComponentOptions are passed to the ComponentService.Create function to create a new JIRA component
|
||||
// CreateComponentOptions are passed to the ComponentService.Create function to create a new Jira component
|
||||
type CreateComponentOptions struct {
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
Description string `json:"description,omitempty" structs:"description,omitempty"`
|
||||
|
@ -19,10 +20,10 @@ type CreateComponentOptions struct {
|
|||
ProjectID int `json:"projectId,omitempty" structs:"projectId,omitempty"`
|
||||
}
|
||||
|
||||
// Create creates a new JIRA component based on the given options.
|
||||
func (s *ComponentService) Create(options *CreateComponentOptions) (*ProjectComponent, *Response, error) {
|
||||
// CreateWithContext creates a new Jira component based on the given options.
|
||||
func (s *ComponentService) CreateWithContext(ctx context.Context, options *CreateComponentOptions) (*ProjectComponent, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/component"
|
||||
req, err := s.client.NewRequest("POST", apiEndpoint, options)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, options)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -36,3 +37,8 @@ func (s *ComponentService) Create(options *CreateComponentOptions) (*ProjectComp
|
|||
|
||||
return component, resp, nil
|
||||
}
|
||||
|
||||
// Create wraps CreateWithContext using the background context.
|
||||
func (s *ComponentService) Create(options *CreateComponentOptions) (*ProjectComponent, *Response, error) {
|
||||
return s.CreateWithContext(context.Background(), options)
|
||||
}
|
||||
|
|
72
vendor/github.com/andygrunwald/go-jira/customer.go
generated
vendored
Normal file
72
vendor/github.com/andygrunwald/go-jira/customer.go
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// CustomerService handles ServiceDesk customers for the Jira instance / API.
|
||||
type CustomerService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Customer represents a ServiceDesk customer.
|
||||
type Customer struct {
|
||||
AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"`
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
Key string `json:"key,omitempty" structs:"key,omitempty"`
|
||||
EmailAddress string `json:"emailAddress,omitempty" structs:"emailAddress,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty" structs:"displayName,omitempty"`
|
||||
Active *bool `json:"active,omitempty" structs:"active,omitempty"`
|
||||
TimeZone string `json:"timeZone,omitempty" structs:"timeZone,omitempty"`
|
||||
Links *SelfLink `json:"_links,omitempty" structs:"_links,omitempty"`
|
||||
}
|
||||
|
||||
// CustomerListOptions is the query options for listing customers.
|
||||
type CustomerListOptions struct {
|
||||
Query string `url:"query,omitempty"`
|
||||
Start int `url:"start,omitempty"`
|
||||
Limit int `url:"limit,omitempty"`
|
||||
}
|
||||
|
||||
// CustomerList is a page of customers.
|
||||
type CustomerList struct {
|
||||
Values []Customer `json:"values,omitempty" structs:"values,omitempty"`
|
||||
Start int `json:"start,omitempty" structs:"start,omitempty"`
|
||||
Limit int `json:"limit,omitempty" structs:"limit,omitempty"`
|
||||
IsLast bool `json:"isLastPage,omitempty" structs:"isLastPage,omitempty"`
|
||||
Expands []string `json:"_expands,omitempty" structs:"_expands,omitempty"`
|
||||
}
|
||||
|
||||
// CreateWithContext creates a ServiceDesk customer.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-customer/#api-rest-servicedeskapi-customer-post
|
||||
func (c *CustomerService) CreateWithContext(ctx context.Context, email, displayName string) (*Customer, *Response, error) {
|
||||
const apiEndpoint = "rest/servicedeskapi/customer"
|
||||
|
||||
payload := struct {
|
||||
Email string `json:"email"`
|
||||
DisplayName string `json:"displayName"`
|
||||
}{
|
||||
Email: email,
|
||||
DisplayName: displayName,
|
||||
}
|
||||
|
||||
req, err := c.client.NewRequestWithContext(ctx, http.MethodPost, apiEndpoint, payload)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
responseCustomer := new(Customer)
|
||||
resp, err := c.client.Do(req, responseCustomer)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
|
||||
return responseCustomer, resp, nil
|
||||
}
|
||||
|
||||
// Create wraps CreateWithContext using the background context.
|
||||
func (c *CustomerService) Create(email, displayName string) (*Customer, *Response, error) {
|
||||
return c.CreateWithContext(context.Background(), email, displayName)
|
||||
}
|
10
vendor/github.com/andygrunwald/go-jira/error.go
generated
vendored
10
vendor/github.com/andygrunwald/go-jira/error.go
generated
vendored
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Error message from JIRA
|
||||
// Error message from Jira
|
||||
// See https://docs.atlassian.com/jira/REST/cloud/#error-responses
|
||||
type Error struct {
|
||||
HTTPError error
|
||||
|
@ -34,13 +34,13 @@ func NewJiraError(resp *Response, httpError error) error {
|
|||
if strings.HasPrefix(contentType, "application/json") {
|
||||
err = json.Unmarshal(body, &jerr)
|
||||
if err != nil {
|
||||
httpError = errors.Wrap(errors.New("Could not parse JSON"), httpError.Error())
|
||||
httpError = errors.Wrap(errors.New("could not parse JSON"), httpError.Error())
|
||||
return errors.Wrap(err, httpError.Error())
|
||||
}
|
||||
} else {
|
||||
if httpError == nil {
|
||||
return fmt.Errorf("Got Response Status %s:%s", resp.Status, string(body))
|
||||
}
|
||||
if httpError == nil {
|
||||
return fmt.Errorf("got response status %s:%s", resp.Status, string(body))
|
||||
}
|
||||
return errors.Wrap(httpError, fmt.Sprintf("%s: %s", resp.Status, string(body)))
|
||||
}
|
||||
|
||||
|
|
30
vendor/github.com/andygrunwald/go-jira/field.go
generated
vendored
30
vendor/github.com/andygrunwald/go-jira/field.go
generated
vendored
|
@ -1,13 +1,15 @@
|
|||
package jira
|
||||
|
||||
// FieldService handles fields for the JIRA instance / API.
|
||||
import "context"
|
||||
|
||||
// FieldService handles fields for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Field
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Field
|
||||
type FieldService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Field represents a field of a JIRA issue.
|
||||
// Field represents a field of a Jira issue.
|
||||
type Field struct {
|
||||
ID string `json:"id,omitempty" structs:"id,omitempty"`
|
||||
Key string `json:"key,omitempty" structs:"key,omitempty"`
|
||||
|
@ -19,17 +21,22 @@ type Field struct {
|
|||
Schema FieldSchema `json:"schema,omitempty" structs:"schema,omitempty"`
|
||||
}
|
||||
|
||||
// FieldSchema represents a schema of a Jira field.
|
||||
// Documentation: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-fields/#api-rest-api-2-field-get
|
||||
type FieldSchema struct {
|
||||
Type string `json:"type,omitempty" structs:"type,omitempty"`
|
||||
System string `json:"system,omitempty" structs:"system,omitempty"`
|
||||
Type string `json:"type,omitempty" structs:"type,omitempty"`
|
||||
Items string `json:"items,omitempty" structs:"items,omitempty"`
|
||||
Custom string `json:"custom,omitempty" structs:"custom,omitempty"`
|
||||
System string `json:"system,omitempty" structs:"system,omitempty"`
|
||||
CustomID int64 `json:"customId,omitempty" structs:"customId,omitempty"`
|
||||
}
|
||||
|
||||
// GetList gets all fields from JIRA
|
||||
// GetListWithContext gets all fields from Jira
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-field-get
|
||||
func (s *FieldService) GetList() ([]Field, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-field-get
|
||||
func (s *FieldService) GetListWithContext(ctx context.Context) ([]Field, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/field"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -41,3 +48,8 @@ func (s *FieldService) GetList() ([]Field, *Response, error) {
|
|||
}
|
||||
return fieldList, resp, nil
|
||||
}
|
||||
|
||||
// GetList wraps GetListWithContext using the background context.
|
||||
func (s *FieldService) GetList() ([]Field, *Response, error) {
|
||||
return s.GetListWithContext(context.Background())
|
||||
}
|
||||
|
|
79
vendor/github.com/andygrunwald/go-jira/filter.go
generated
vendored
79
vendor/github.com/andygrunwald/go-jira/filter.go
generated
vendored
|
@ -1,11 +1,15 @@
|
|||
package jira
|
||||
|
||||
import "github.com/google/go-querystring/query"
|
||||
import "fmt"
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
// FilterService handles fields for the JIRA instance / API.
|
||||
"github.com/google/go-querystring/query"
|
||||
)
|
||||
|
||||
// FilterService handles fields for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Filter
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Filter
|
||||
type FilterService struct {
|
||||
client *Client
|
||||
}
|
||||
|
@ -116,23 +120,21 @@ type FilterSearchOptions struct {
|
|||
Expand string `url:"expand,omitempty"`
|
||||
}
|
||||
|
||||
// GetList retrieves all filters from Jira
|
||||
func (fs *FilterService) GetList() ([]*Filter, *Response, error) {
|
||||
// GetListWithContext retrieves all filters from Jira
|
||||
func (fs *FilterService) GetListWithContext(ctx context.Context) ([]*Filter, *Response, error) {
|
||||
|
||||
options := &GetQueryOptions{}
|
||||
apiEndpoint := "rest/api/2/filter"
|
||||
req, err := fs.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := fs.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if options != nil {
|
||||
q, err := query.Values(options)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
q, err := query.Values(options)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
|
||||
filters := []*Filter{}
|
||||
resp, err := fs.client.Do(req, &filters)
|
||||
|
@ -143,10 +145,15 @@ func (fs *FilterService) GetList() ([]*Filter, *Response, error) {
|
|||
return filters, resp, err
|
||||
}
|
||||
|
||||
// GetFavouriteList retrieves the user's favourited filters from Jira
|
||||
func (fs *FilterService) GetFavouriteList() ([]*Filter, *Response, error) {
|
||||
// GetList wraps GetListWithContext using the background context.
|
||||
func (fs *FilterService) GetList() ([]*Filter, *Response, error) {
|
||||
return fs.GetListWithContext(context.Background())
|
||||
}
|
||||
|
||||
// GetFavouriteListWithContext retrieves the user's favourited filters from Jira
|
||||
func (fs *FilterService) GetFavouriteListWithContext(ctx context.Context) ([]*Filter, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/filter/favourite"
|
||||
req, err := fs.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := fs.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -159,10 +166,15 @@ func (fs *FilterService) GetFavouriteList() ([]*Filter, *Response, error) {
|
|||
return filters, resp, err
|
||||
}
|
||||
|
||||
// Get retrieves a single Filter from Jira
|
||||
func (fs *FilterService) Get(filterID int) (*Filter, *Response, error) {
|
||||
// GetFavouriteList wraps GetFavouriteListWithContext using the background context.
|
||||
func (fs *FilterService) GetFavouriteList() ([]*Filter, *Response, error) {
|
||||
return fs.GetFavouriteListWithContext(context.Background())
|
||||
}
|
||||
|
||||
// GetWithContext retrieves a single Filter from Jira
|
||||
func (fs *FilterService) GetWithContext(ctx context.Context, filterID int) (*Filter, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/api/2/filter/%d", filterID)
|
||||
req, err := fs.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := fs.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -176,16 +188,21 @@ func (fs *FilterService) Get(filterID int) (*Filter, *Response, error) {
|
|||
return filter, resp, err
|
||||
}
|
||||
|
||||
// GetMyFilters retrieves the my Filters.
|
||||
// Get wraps GetWithContext using the background context.
|
||||
func (fs *FilterService) Get(filterID int) (*Filter, *Response, error) {
|
||||
return fs.GetWithContext(context.Background(), filterID)
|
||||
}
|
||||
|
||||
// GetMyFiltersWithContext retrieves the my Filters.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-my-get
|
||||
func (fs *FilterService) GetMyFilters(opts *GetMyFiltersQueryOptions) ([]*Filter, *Response, error) {
|
||||
func (fs *FilterService) GetMyFiltersWithContext(ctx context.Context, opts *GetMyFiltersQueryOptions) ([]*Filter, *Response, error) {
|
||||
apiEndpoint := "rest/api/3/filter/my"
|
||||
url, err := addOptions(apiEndpoint, opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := fs.client.NewRequest("GET", url, nil)
|
||||
req, err := fs.client.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -199,16 +216,21 @@ func (fs *FilterService) GetMyFilters(opts *GetMyFiltersQueryOptions) ([]*Filter
|
|||
return filters, resp, nil
|
||||
}
|
||||
|
||||
// Search will search for filter according to the search options
|
||||
// GetMyFilters wraps GetMyFiltersWithContext using the background context.
|
||||
func (fs *FilterService) GetMyFilters(opts *GetMyFiltersQueryOptions) ([]*Filter, *Response, error) {
|
||||
return fs.GetMyFiltersWithContext(context.Background(), opts)
|
||||
}
|
||||
|
||||
// SearchWithContext will search for filter according to the search options
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-search-get
|
||||
func (fs *FilterService) Search(opt *FilterSearchOptions) (*FiltersList, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-search-get
|
||||
func (fs *FilterService) SearchWithContext(ctx context.Context, opt *FilterSearchOptions) (*FiltersList, *Response, error) {
|
||||
apiEndpoint := "rest/api/3/filter/search"
|
||||
url, err := addOptions(apiEndpoint, opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := fs.client.NewRequest("GET", url, nil)
|
||||
req, err := fs.client.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -222,3 +244,8 @@ func (fs *FilterService) Search(opt *FilterSearchOptions) (*FiltersList, *Respon
|
|||
|
||||
return filters, resp, err
|
||||
}
|
||||
|
||||
// Search wraps SearchWithContext using the background context.
|
||||
func (fs *FilterService) Search(opt *FilterSearchOptions) (*FiltersList, *Response, error) {
|
||||
return fs.SearchWithContext(context.Background(), opt)
|
||||
}
|
||||
|
|
61
vendor/github.com/andygrunwald/go-jira/group.go
generated
vendored
61
vendor/github.com/andygrunwald/go-jira/group.go
generated
vendored
|
@ -1,13 +1,14 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// GroupService handles Groups for the JIRA instance / API.
|
||||
// GroupService handles Groups for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group
|
||||
type GroupService struct {
|
||||
client *Client
|
||||
}
|
||||
|
@ -21,7 +22,7 @@ type groupMembersResult struct {
|
|||
Members []GroupMember `json:"values"`
|
||||
}
|
||||
|
||||
// Group represents a JIRA group
|
||||
// Group represents a Jira group
|
||||
type Group struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
|
@ -58,16 +59,16 @@ type GroupSearchOptions struct {
|
|||
IncludeInactiveUsers bool
|
||||
}
|
||||
|
||||
// Get returns a paginated list of users who are members of the specified group and its subgroups.
|
||||
// GetWithContext returns a paginated list of users who are members of the specified group and its subgroups.
|
||||
// Users in the page are ordered by user names.
|
||||
// User of this resource is required to have sysadmin or admin permissions.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group-getUsersFromGroup
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group-getUsersFromGroup
|
||||
//
|
||||
// WARNING: This API only returns the first page of group members
|
||||
func (s *GroupService) Get(name string) ([]GroupMember, *Response, error) {
|
||||
func (s *GroupService) GetWithContext(ctx context.Context, name string) ([]GroupMember, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/group/member?groupname=%s", url.QueryEscape(name))
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -81,12 +82,17 @@ func (s *GroupService) Get(name string) ([]GroupMember, *Response, error) {
|
|||
return group.Members, resp, nil
|
||||
}
|
||||
|
||||
// GetWithOptions returns a paginated list of members of the specified group and its subgroups.
|
||||
// Get wraps GetWithContext using the background context.
|
||||
func (s *GroupService) Get(name string) ([]GroupMember, *Response, error) {
|
||||
return s.GetWithContext(context.Background(), name)
|
||||
}
|
||||
|
||||
// GetWithOptionsWithContext returns a paginated list of members of the specified group and its subgroups.
|
||||
// Users in the page are ordered by user names.
|
||||
// User of this resource is required to have sysadmin or admin permissions.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group-getUsersFromGroup
|
||||
func (s *GroupService) GetWithOptions(name string, options *GroupSearchOptions) ([]GroupMember, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group-getUsersFromGroup
|
||||
func (s *GroupService) GetWithOptionsWithContext(ctx context.Context, name string, options *GroupSearchOptions) ([]GroupMember, *Response, error) {
|
||||
var apiEndpoint string
|
||||
if options == nil {
|
||||
apiEndpoint = fmt.Sprintf("/rest/api/2/group/member?groupname=%s", url.QueryEscape(name))
|
||||
|
@ -99,7 +105,7 @@ func (s *GroupService) GetWithOptions(name string, options *GroupSearchOptions)
|
|||
options.IncludeInactiveUsers,
|
||||
)
|
||||
}
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -112,16 +118,21 @@ func (s *GroupService) GetWithOptions(name string, options *GroupSearchOptions)
|
|||
return group.Members, resp, nil
|
||||
}
|
||||
|
||||
// Add adds user to group
|
||||
// GetWithOptions wraps GetWithOptionsWithContext using the background context.
|
||||
func (s *GroupService) GetWithOptions(name string, options *GroupSearchOptions) ([]GroupMember, *Response, error) {
|
||||
return s.GetWithOptionsWithContext(context.Background(), name, options)
|
||||
}
|
||||
|
||||
// AddWithContext adds user to group
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/group-addUserToGroup
|
||||
func (s *GroupService) Add(groupname string, username string) (*Group, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/group-addUserToGroup
|
||||
func (s *GroupService) AddWithContext(ctx context.Context, groupname string, username string) (*Group, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/group/user?groupname=%s", groupname)
|
||||
var user struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
user.Name = username
|
||||
req, err := s.client.NewRequest("POST", apiEndpoint, &user)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, &user)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -136,12 +147,18 @@ func (s *GroupService) Add(groupname string, username string) (*Group, *Response
|
|||
return responseGroup, resp, nil
|
||||
}
|
||||
|
||||
// Remove removes user from group
|
||||
// Add wraps AddWithContext using the background context.
|
||||
func (s *GroupService) Add(groupname string, username string) (*Group, *Response, error) {
|
||||
return s.AddWithContext(context.Background(), groupname, username)
|
||||
}
|
||||
|
||||
// RemoveWithContext removes user from group
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/group-removeUserFromGroup
|
||||
func (s *GroupService) Remove(groupname string, username string) (*Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/group-removeUserFromGroup
|
||||
// Caller must close resp.Body
|
||||
func (s *GroupService) RemoveWithContext(ctx context.Context, groupname string, username string) (*Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/group/user?groupname=%s&username=%s", groupname, username)
|
||||
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -154,3 +171,9 @@ func (s *GroupService) Remove(groupname string, username string) (*Response, err
|
|||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Remove wraps RemoveWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *GroupService) Remove(groupname string, username string) (*Response, error) {
|
||||
return s.RemoveWithContext(context.Background(), groupname, username)
|
||||
}
|
||||
|
|
629
vendor/github.com/andygrunwald/go-jira/issue.go
generated
vendored
629
vendor/github.com/andygrunwald/go-jira/issue.go
generated
vendored
File diff suppressed because it is too large
Load diff
78
vendor/github.com/andygrunwald/go-jira/issuelinktype.go
generated
vendored
78
vendor/github.com/andygrunwald/go-jira/issuelinktype.go
generated
vendored
|
@ -1,24 +1,25 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// IssueLinkTypeService handles issue link types for the JIRA instance / API.
|
||||
// IssueLinkTypeService handles issue link types for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Issue-link-types
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Issue-link-types
|
||||
type IssueLinkTypeService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// GetList gets all of the issue link types from JIRA.
|
||||
// GetListWithContext gets all of the issue link types from Jira.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-get
|
||||
func (s *IssueLinkTypeService) GetList() ([]IssueLinkType, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-get
|
||||
func (s *IssueLinkTypeService) GetListWithContext(ctx context.Context) ([]IssueLinkType, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/issueLinkType"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -31,12 +32,17 @@ func (s *IssueLinkTypeService) GetList() ([]IssueLinkType, *Response, error) {
|
|||
return linkTypeList, resp, nil
|
||||
}
|
||||
|
||||
// Get gets info of a specific issue link type from JIRA.
|
||||
// GetList wraps GetListWithContext using the background context.
|
||||
func (s *IssueLinkTypeService) GetList() ([]IssueLinkType, *Response, error) {
|
||||
return s.GetListWithContext(context.Background())
|
||||
}
|
||||
|
||||
// GetWithContext gets info of a specific issue link type from Jira.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-get
|
||||
func (s *IssueLinkTypeService) Get(ID string) (*IssueLinkType, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-get
|
||||
func (s *IssueLinkTypeService) GetWithContext(ctx context.Context, ID string) (*IssueLinkType, *Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", ID)
|
||||
req, err := s.client.NewRequest("GET", apiEndPoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -49,12 +55,17 @@ func (s *IssueLinkTypeService) Get(ID string) (*IssueLinkType, *Response, error)
|
|||
return linkType, resp, nil
|
||||
}
|
||||
|
||||
// Create creates an issue link type in JIRA.
|
||||
// Get wraps GetWithContext using the background context.
|
||||
func (s *IssueLinkTypeService) Get(ID string) (*IssueLinkType, *Response, error) {
|
||||
return s.GetWithContext(context.Background(), ID)
|
||||
}
|
||||
|
||||
// CreateWithContext creates an issue link type in Jira.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-post
|
||||
func (s *IssueLinkTypeService) Create(linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-post
|
||||
func (s *IssueLinkTypeService) CreateWithContext(ctx context.Context, linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
|
||||
apiEndpoint := "/rest/api/2/issueLinkType"
|
||||
req, err := s.client.NewRequest("POST", apiEndpoint, linkType)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, linkType)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -68,23 +79,29 @@ func (s *IssueLinkTypeService) Create(linkType *IssueLinkType) (*IssueLinkType,
|
|||
defer resp.Body.Close()
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
e := fmt.Errorf("Could not read the returned data")
|
||||
e := fmt.Errorf("could not read the returned data")
|
||||
return nil, resp, NewJiraError(resp, e)
|
||||
}
|
||||
err = json.Unmarshal(data, responseLinkType)
|
||||
if err != nil {
|
||||
e := fmt.Errorf("Could no unmarshal the data into struct")
|
||||
e := fmt.Errorf("could no unmarshal the data into struct")
|
||||
return nil, resp, NewJiraError(resp, e)
|
||||
}
|
||||
return linkType, resp, nil
|
||||
}
|
||||
|
||||
// Update updates an issue link type. The issue is found by key.
|
||||
// Create wraps CreateWithContext using the background context.
|
||||
func (s *IssueLinkTypeService) Create(linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
|
||||
return s.CreateWithContext(context.Background(), linkType)
|
||||
}
|
||||
|
||||
// UpdateWithContext updates an issue link type. The issue is found by key.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-put
|
||||
func (s *IssueLinkTypeService) Update(linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-put
|
||||
// Caller must close resp.Body
|
||||
func (s *IssueLinkTypeService) UpdateWithContext(ctx context.Context, linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", linkType.ID)
|
||||
req, err := s.client.NewRequest("PUT", apiEndpoint, linkType)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, linkType)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -96,12 +113,19 @@ func (s *IssueLinkTypeService) Update(linkType *IssueLinkType) (*IssueLinkType,
|
|||
return &ret, resp, nil
|
||||
}
|
||||
|
||||
// Delete deletes an issue link type based on provided ID.
|
||||
// Update wraps UpdateWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *IssueLinkTypeService) Update(linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
|
||||
return s.UpdateWithContext(context.Background(), linkType)
|
||||
}
|
||||
|
||||
// DeleteWithContext deletes an issue link type based on provided ID.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-delete
|
||||
func (s *IssueLinkTypeService) Delete(ID string) (*Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-delete
|
||||
// Caller must close resp.Body
|
||||
func (s *IssueLinkTypeService) DeleteWithContext(ctx context.Context, ID string) (*Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", ID)
|
||||
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -109,3 +133,9 @@ func (s *IssueLinkTypeService) Delete(ID string) (*Response, error) {
|
|||
resp, err := s.client.Do(req, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Delete wraps DeleteWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *IssueLinkTypeService) Delete(ID string) (*Response, error) {
|
||||
return s.DeleteWithContext(context.Background(), ID)
|
||||
}
|
||||
|
|
137
vendor/github.com/andygrunwald/go-jira/jira.go
generated
vendored
137
vendor/github.com/andygrunwald/go-jira/jira.go
generated
vendored
|
@ -2,6 +2,7 @@ package jira
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
@ -14,7 +15,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
jwt "github.com/golang-jwt/jwt/v4"
|
||||
"github.com/google/go-querystring/query"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -25,7 +26,7 @@ type httpClient interface {
|
|||
Do(request *http.Request) (response *http.Response, err error)
|
||||
}
|
||||
|
||||
// A Client manages communication with the JIRA API.
|
||||
// A Client manages communication with the Jira API.
|
||||
type Client struct {
|
||||
// HTTP client used to communicate with the API.
|
||||
client httpClient
|
||||
|
@ -36,7 +37,7 @@ type Client struct {
|
|||
// Session storage if the user authenticates with a Session cookie
|
||||
session *Session
|
||||
|
||||
// Services used for talking to different parts of the JIRA API.
|
||||
// Services used for talking to different parts of the Jira API.
|
||||
Authentication *AuthenticationService
|
||||
Issue *IssueService
|
||||
Project *ProjectService
|
||||
|
@ -55,15 +56,19 @@ type Client struct {
|
|||
PermissionScheme *PermissionSchemeService
|
||||
Status *StatusService
|
||||
IssueLinkType *IssueLinkTypeService
|
||||
Organization *OrganizationService
|
||||
ServiceDesk *ServiceDeskService
|
||||
Customer *CustomerService
|
||||
Request *RequestService
|
||||
}
|
||||
|
||||
// NewClient returns a new JIRA API client.
|
||||
// NewClient returns a new Jira API client.
|
||||
// If a nil httpClient is provided, http.DefaultClient will be used.
|
||||
// To use API methods which require authentication you can follow the preferred solution and
|
||||
// provide an http.Client that will perform the authentication for you with OAuth and HTTP Basic (such as that provided by the golang.org/x/oauth2 library).
|
||||
// As an alternative you can use Session Cookie based authentication provided by this package as well.
|
||||
// See https://docs.atlassian.com/jira/REST/latest/#authentication
|
||||
// baseURL is the HTTP endpoint of your JIRA instance and should always be specified with a trailing slash.
|
||||
// baseURL is the HTTP endpoint of your Jira instance and should always be specified with a trailing slash.
|
||||
func NewClient(httpClient httpClient, baseURL string) (*Client, error) {
|
||||
if httpClient == nil {
|
||||
httpClient = http.DefaultClient
|
||||
|
@ -101,14 +106,18 @@ func NewClient(httpClient httpClient, baseURL string) (*Client, error) {
|
|||
c.PermissionScheme = &PermissionSchemeService{client: c}
|
||||
c.Status = &StatusService{client: c}
|
||||
c.IssueLinkType = &IssueLinkTypeService{client: c}
|
||||
c.Organization = &OrganizationService{client: c}
|
||||
c.ServiceDesk = &ServiceDeskService{client: c}
|
||||
c.Customer = &CustomerService{client: c}
|
||||
c.Request = &RequestService{client: c}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// NewRawRequest creates an API request.
|
||||
// NewRawRequestWithContext creates an API request.
|
||||
// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client.
|
||||
// Allows using an optional native io.Reader for sourcing the request body.
|
||||
func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Request, error) {
|
||||
func (c *Client) NewRawRequestWithContext(ctx context.Context, method, urlStr string, body io.Reader) (*http.Request, error) {
|
||||
rel, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -118,7 +127,7 @@ func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Req
|
|||
|
||||
u := c.baseURL.ResolveReference(rel)
|
||||
|
||||
req, err := http.NewRequest(method, u.String(), body)
|
||||
req, err := newRequestWithContext(ctx, method, u.String(), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -143,10 +152,15 @@ func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Req
|
|||
return req, nil
|
||||
}
|
||||
|
||||
// NewRequest creates an API request.
|
||||
// NewRawRequest wraps NewRawRequestWithContext using the background context.
|
||||
func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Request, error) {
|
||||
return c.NewRawRequestWithContext(context.Background(), method, urlStr, body)
|
||||
}
|
||||
|
||||
// NewRequestWithContext creates an API request.
|
||||
// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client.
|
||||
// If specified, the value pointed to by body is JSON encoded and included as the request body.
|
||||
func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
|
||||
func (c *Client) NewRequestWithContext(ctx context.Context, method, urlStr string, body interface{}) (*http.Request, error) {
|
||||
rel, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -165,7 +179,7 @@ func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Requ
|
|||
}
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(method, u.String(), buf)
|
||||
req, err := newRequestWithContext(ctx, method, u.String(), buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -190,6 +204,11 @@ func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Requ
|
|||
return req, nil
|
||||
}
|
||||
|
||||
// NewRequest wraps NewRequestWithContext using the background context.
|
||||
func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
|
||||
return c.NewRequestWithContext(context.Background(), method, urlStr, body)
|
||||
}
|
||||
|
||||
// addOptions adds the parameters in opt as URL query parameters to s. opt
|
||||
// must be a struct whose fields may contain "url" tags.
|
||||
func addOptions(s string, opt interface{}) (string, error) {
|
||||
|
@ -212,10 +231,10 @@ func addOptions(s string, opt interface{}) (string, error) {
|
|||
return u.String(), nil
|
||||
}
|
||||
|
||||
// NewMultiPartRequest creates an API request including a multi-part file.
|
||||
// NewMultiPartRequestWithContext creates an API request including a multi-part file.
|
||||
// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client.
|
||||
// If specified, the value pointed to by buf is a multipart form.
|
||||
func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (*http.Request, error) {
|
||||
func (c *Client) NewMultiPartRequestWithContext(ctx context.Context, method, urlStr string, buf *bytes.Buffer) (*http.Request, error) {
|
||||
rel, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -225,7 +244,7 @@ func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (
|
|||
|
||||
u := c.baseURL.ResolveReference(rel)
|
||||
|
||||
req, err := http.NewRequest(method, u.String(), buf)
|
||||
req, err := newRequestWithContext(ctx, method, u.String(), buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -251,6 +270,11 @@ func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (
|
|||
return req, nil
|
||||
}
|
||||
|
||||
// NewMultiPartRequest wraps NewMultiPartRequestWithContext using the background context.
|
||||
func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (*http.Request, error) {
|
||||
return c.NewMultiPartRequestWithContext(context.Background(), method, urlStr, buf)
|
||||
}
|
||||
|
||||
// Do sends an API request and returns the API response.
|
||||
// The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred.
|
||||
func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
|
||||
|
@ -279,13 +303,13 @@ func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
|
|||
// CheckResponse checks the API response for errors, and returns them if present.
|
||||
// A response is considered an error if it has a status code outside the 200 range.
|
||||
// The caller is responsible to analyze the response body.
|
||||
// The body can contain JSON (if the error is intended) or xml (sometimes JIRA just failes).
|
||||
// The body can contain JSON (if the error is intended) or xml (sometimes Jira just failes).
|
||||
func CheckResponse(r *http.Response) error {
|
||||
if c := r.StatusCode; 200 <= c && c <= 299 {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := fmt.Errorf("Request failed. Please analyze the request body for more details. Status code: %d", r.StatusCode)
|
||||
err := fmt.Errorf("request failed. Please analyze the request body for more details. Status code: %d", r.StatusCode)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -295,7 +319,7 @@ func (c *Client) GetBaseURL() url.URL {
|
|||
return *c.baseURL
|
||||
}
|
||||
|
||||
// Response represents JIRA API response. It wraps http.Response returned from
|
||||
// Response represents Jira API response. It wraps http.Response returned from
|
||||
// API and provides information about paging.
|
||||
type Response struct {
|
||||
*http.Response
|
||||
|
@ -324,7 +348,6 @@ func (r *Response) populatePageValues(v interface{}) {
|
|||
r.MaxResults = value.MaxResults
|
||||
r.Total = value.Total
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BasicAuthTransport is an http.RoundTripper that authenticates all requests
|
||||
|
@ -363,13 +386,84 @@ func (t *BasicAuthTransport) transport() http.RoundTripper {
|
|||
return http.DefaultTransport
|
||||
}
|
||||
|
||||
// BearerAuthTransport is a http.RoundTripper that authenticates all requests
|
||||
// using Jira's bearer (oauth 2.0 (3lo)) based authentication.
|
||||
type BearerAuthTransport struct {
|
||||
Token string
|
||||
|
||||
// Transport is the underlying HTTP transport to use when making requests.
|
||||
// It will default to http.DefaultTransport if nil.
|
||||
Transport http.RoundTripper
|
||||
}
|
||||
|
||||
// RoundTrip implements the RoundTripper interface. We just add the
|
||||
// bearer token and return the RoundTripper for this transport type.
|
||||
func (t *BearerAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
req2 := cloneRequest(req) // per RoundTripper contract
|
||||
|
||||
req2.Header.Set("Authorization", fmt.Sprintf("Bearer %s", t.Token))
|
||||
return t.transport().RoundTrip(req2)
|
||||
}
|
||||
|
||||
// Client returns an *http.Client that makes requests that are authenticated
|
||||
// using HTTP Basic Authentication. This is a nice little bit of sugar
|
||||
// so we can just get the client instead of creating the client in the calling code.
|
||||
// If it's necessary to send more information on client init, the calling code can
|
||||
// always skip this and set the transport itself.
|
||||
func (t *BearerAuthTransport) Client() *http.Client {
|
||||
return &http.Client{Transport: t}
|
||||
}
|
||||
|
||||
func (t *BearerAuthTransport) transport() http.RoundTripper {
|
||||
if t.Transport != nil {
|
||||
return t.Transport
|
||||
}
|
||||
return http.DefaultTransport
|
||||
}
|
||||
|
||||
// PATAuthTransport is an http.RoundTripper that authenticates all requests
|
||||
// using the Personal Access Token specified.
|
||||
// See here for more info: https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html
|
||||
type PATAuthTransport struct {
|
||||
// Token is the key that was provided by Jira when creating the Personal Access Token.
|
||||
Token string
|
||||
|
||||
// Transport is the underlying HTTP transport to use when making requests.
|
||||
// It will default to http.DefaultTransport if nil.
|
||||
Transport http.RoundTripper
|
||||
}
|
||||
|
||||
// RoundTrip implements the RoundTripper interface. We just add the
|
||||
// basic auth and return the RoundTripper for this transport type.
|
||||
func (t *PATAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
req2 := cloneRequest(req) // per RoundTripper contract
|
||||
req2.Header.Set("Authorization", "Bearer "+t.Token)
|
||||
return t.transport().RoundTrip(req2)
|
||||
}
|
||||
|
||||
// Client returns an *http.Client that makes requests that are authenticated
|
||||
// using HTTP Basic Authentication. This is a nice little bit of sugar
|
||||
// so we can just get the client instead of creating the client in the calling code.
|
||||
// If it's necessary to send more information on client init, the calling code can
|
||||
// always skip this and set the transport itself.
|
||||
func (t *PATAuthTransport) Client() *http.Client {
|
||||
return &http.Client{Transport: t}
|
||||
}
|
||||
|
||||
func (t *PATAuthTransport) transport() http.RoundTripper {
|
||||
if t.Transport != nil {
|
||||
return t.Transport
|
||||
}
|
||||
return http.DefaultTransport
|
||||
}
|
||||
|
||||
// CookieAuthTransport is an http.RoundTripper that authenticates all requests
|
||||
// using Jira's cookie-based authentication.
|
||||
//
|
||||
// Note that it is generally preferable to use HTTP BASIC authentication with the REST API.
|
||||
// However, this resource may be used to mimic the behaviour of JIRA's log-in page (e.g. to display log-in errors to a user).
|
||||
// However, this resource may be used to mimic the behaviour of Jira's log-in page (e.g. to display log-in errors to a user).
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
|
||||
type CookieAuthTransport struct {
|
||||
Username string
|
||||
Password string
|
||||
|
@ -425,6 +519,7 @@ func (t *CookieAuthTransport) setSessionObject() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
t.SessionObject = resp.Cookies()
|
||||
return nil
|
||||
|
@ -464,7 +559,7 @@ func (t *CookieAuthTransport) transport() http.RoundTripper {
|
|||
//
|
||||
// NOTE: this form of auth should be used by add-ons installed from the Atlassian marketplace.
|
||||
//
|
||||
// JIRA docs: https://developer.atlassian.com/cloud/jira/platform/understanding-jwt
|
||||
// Jira docs: https://developer.atlassian.com/cloud/jira/platform/understanding-jwt
|
||||
// Examples in other languages:
|
||||
// https://bitbucket.org/atlassian/atlassian-jwt-ruby/src/d44a8e7a4649e4f23edaa784402655fda7c816ea/lib/atlassian/jwt.rb
|
||||
// https://bitbucket.org/atlassian/atlassian-jwt-py/src/master/atlassian_jwt/url_utils.py
|
||||
|
|
62
vendor/github.com/andygrunwald/go-jira/metaissue.go
generated
vendored
62
vendor/github.com/andygrunwald/go-jira/metaissue.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
@ -14,6 +15,11 @@ type CreateMetaInfo struct {
|
|||
Projects []*MetaProject `json:"projects,omitempty"`
|
||||
}
|
||||
|
||||
// EditMetaInfo contains information about fields and their attributed to edit a ticket.
|
||||
type EditMetaInfo struct {
|
||||
Fields tcontainer.MarshalMap `json:"fields,omitempty"`
|
||||
}
|
||||
|
||||
// MetaProject is the meta information about a project returned from createmeta api
|
||||
type MetaProject struct {
|
||||
Expand string `json:"expand,omitempty"`
|
||||
|
@ -42,16 +48,21 @@ type MetaIssueType struct {
|
|||
Fields tcontainer.MarshalMap `json:"fields,omitempty"`
|
||||
}
|
||||
|
||||
// GetCreateMeta makes the api call to get the meta information required to create a ticket
|
||||
func (s *IssueService) GetCreateMeta(projectkeys string) (*CreateMetaInfo, *Response, error) {
|
||||
return s.GetCreateMetaWithOptions(&GetQueryOptions{ProjectKeys: projectkeys, Expand: "projects.issuetypes.fields"})
|
||||
// GetCreateMetaWithContext makes the api call to get the meta information required to create a ticket
|
||||
func (s *IssueService) GetCreateMetaWithContext(ctx context.Context, projectkeys string) (*CreateMetaInfo, *Response, error) {
|
||||
return s.GetCreateMetaWithOptionsWithContext(ctx, &GetQueryOptions{ProjectKeys: projectkeys, Expand: "projects.issuetypes.fields"})
|
||||
}
|
||||
|
||||
// GetCreateMetaWithOptions makes the api call to get the meta information without requiring to have a projectKey
|
||||
func (s *IssueService) GetCreateMetaWithOptions(options *GetQueryOptions) (*CreateMetaInfo, *Response, error) {
|
||||
// GetCreateMeta wraps GetCreateMetaWithContext using the background context.
|
||||
func (s *IssueService) GetCreateMeta(projectkeys string) (*CreateMetaInfo, *Response, error) {
|
||||
return s.GetCreateMetaWithContext(context.Background(), projectkeys)
|
||||
}
|
||||
|
||||
// GetCreateMetaWithOptionsWithContext makes the api call to get the meta information without requiring to have a projectKey
|
||||
func (s *IssueService) GetCreateMetaWithOptionsWithContext(ctx context.Context, options *GetQueryOptions) (*CreateMetaInfo, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/issue/createmeta"
|
||||
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -73,11 +84,40 @@ func (s *IssueService) GetCreateMetaWithOptions(options *GetQueryOptions) (*Crea
|
|||
return meta, resp, nil
|
||||
}
|
||||
|
||||
// GetCreateMetaWithOptions wraps GetCreateMetaWithOptionsWithContext using the background context.
|
||||
func (s *IssueService) GetCreateMetaWithOptions(options *GetQueryOptions) (*CreateMetaInfo, *Response, error) {
|
||||
return s.GetCreateMetaWithOptionsWithContext(context.Background(), options)
|
||||
}
|
||||
|
||||
// GetEditMetaWithContext makes the api call to get the edit meta information for an issue
|
||||
func (s *IssueService) GetEditMetaWithContext(ctx context.Context, issue *Issue) (*EditMetaInfo, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/issue/%s/editmeta", issue.Key)
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
meta := new(EditMetaInfo)
|
||||
resp, err := s.client.Do(req, meta)
|
||||
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return meta, resp, nil
|
||||
}
|
||||
|
||||
// GetEditMeta wraps GetEditMetaWithContext using the background context.
|
||||
func (s *IssueService) GetEditMeta(issue *Issue) (*EditMetaInfo, *Response, error) {
|
||||
return s.GetEditMetaWithContext(context.Background(), issue)
|
||||
}
|
||||
|
||||
// GetProjectWithName returns a project with "name" from the meta information received. If not found, this returns nil.
|
||||
// The comparison of the name is case insensitive.
|
||||
func (m *CreateMetaInfo) GetProjectWithName(name string) *MetaProject {
|
||||
for _, m := range m.Projects {
|
||||
if strings.ToLower(m.Name) == strings.ToLower(name) {
|
||||
if strings.EqualFold(m.Name, name) {
|
||||
return m
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +128,7 @@ func (m *CreateMetaInfo) GetProjectWithName(name string) *MetaProject {
|
|||
// The comparison of the name is case insensitive.
|
||||
func (m *CreateMetaInfo) GetProjectWithKey(key string) *MetaProject {
|
||||
for _, m := range m.Projects {
|
||||
if strings.ToLower(m.Key) == strings.ToLower(key) {
|
||||
if strings.EqualFold(m.Key, key) {
|
||||
return m
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +139,7 @@ func (m *CreateMetaInfo) GetProjectWithKey(key string) *MetaProject {
|
|||
// The comparison of the name is case insensitive
|
||||
func (p *MetaProject) GetIssueTypeWithName(name string) *MetaIssueType {
|
||||
for _, m := range p.IssueTypes {
|
||||
if strings.ToLower(m.Name) == strings.ToLower(name) {
|
||||
if strings.EqualFold(m.Name, name) {
|
||||
return m
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +215,7 @@ func (t *MetaIssueType) CheckCompleteAndAvailable(config map[string]string) (boo
|
|||
for name := range mandatory {
|
||||
requiredFields = append(requiredFields, name)
|
||||
}
|
||||
return false, fmt.Errorf("Required field not found in provided jira.fields. Required are: %#v", requiredFields)
|
||||
return false, fmt.Errorf("required field not found in provided jira.fields. Required are: %#v", requiredFields)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,7 +226,7 @@ func (t *MetaIssueType) CheckCompleteAndAvailable(config map[string]string) (boo
|
|||
for name := range all {
|
||||
availableFields = append(availableFields, name)
|
||||
}
|
||||
return false, fmt.Errorf("Fields in jira.fields are not available in jira. Available are: %#v", availableFields)
|
||||
return false, fmt.Errorf("fields in jira.fields are not available in jira. Available are: %#v", availableFields)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
397
vendor/github.com/andygrunwald/go-jira/organization.go
generated
vendored
Normal file
397
vendor/github.com/andygrunwald/go-jira/organization.go
generated
vendored
Normal file
|
@ -0,0 +1,397 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// OrganizationService handles Organizations for the Jira instance / API.
|
||||
//
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/
|
||||
type OrganizationService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// OrganizationCreationDTO is DTO for creat organization API
|
||||
type OrganizationCreationDTO struct {
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
}
|
||||
|
||||
// SelfLink Stores REST API URL to the organization.
|
||||
type SelfLink struct {
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
}
|
||||
|
||||
// Organization contains Organization data
|
||||
type Organization struct {
|
||||
ID string `json:"id,omitempty" structs:"id,omitempty"`
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
Links *SelfLink `json:"_links,omitempty" structs:"_links,omitempty"`
|
||||
}
|
||||
|
||||
// OrganizationUsersDTO contains organization user ids
|
||||
type OrganizationUsersDTO struct {
|
||||
AccountIds []string `json:"accountIds,omitempty" structs:"accountIds,omitempty"`
|
||||
}
|
||||
|
||||
// PagedDTO is response of a paged list
|
||||
type PagedDTO struct {
|
||||
Size int `json:"size,omitempty" structs:"size,omitempty"`
|
||||
Start int `json:"start,omitempty" structs:"start,omitempty"`
|
||||
Limit int `limit:"size,omitempty" structs:"limit,omitempty"`
|
||||
IsLastPage bool `json:"isLastPage,omitempty" structs:"isLastPage,omitempty"`
|
||||
Values []interface{} `values:"isLastPage,omitempty" structs:"values,omitempty"`
|
||||
Expands []string `json:"_expands,omitempty" structs:"_expands,omitempty"`
|
||||
}
|
||||
|
||||
// PropertyKey contains Property key details.
|
||||
type PropertyKey struct {
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
Key string `json:"key,omitempty" structs:"key,omitempty"`
|
||||
}
|
||||
|
||||
// PropertyKeys contains an array of PropertyKey
|
||||
type PropertyKeys struct {
|
||||
Keys []PropertyKey `json:"keys,omitempty" structs:"keys,omitempty"`
|
||||
}
|
||||
|
||||
// GetAllOrganizationsWithContext returns a list of organizations in
|
||||
// the Jira Service Management instance.
|
||||
// Use this method when you want to present a list
|
||||
// of organizations or want to locate an organization
|
||||
// by name.
|
||||
//
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-group-organization
|
||||
func (s *OrganizationService) GetAllOrganizationsWithContext(ctx context.Context, start int, limit int, accountID string) (*PagedDTO, *Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization?start=%d&limit=%d", start, limit)
|
||||
if accountID != "" {
|
||||
apiEndPoint += fmt.Sprintf("&accountId=%s", accountID)
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
v := new(PagedDTO)
|
||||
resp, err := s.client.Do(req, v)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
|
||||
return v, resp, nil
|
||||
}
|
||||
|
||||
// GetAllOrganizations wraps GetAllOrganizationsWithContext using the background context.
|
||||
func (s *OrganizationService) GetAllOrganizations(start int, limit int, accountID string) (*PagedDTO, *Response, error) {
|
||||
return s.GetAllOrganizationsWithContext(context.Background(), start, limit, accountID)
|
||||
}
|
||||
|
||||
// CreateOrganizationWithContext creates an organization by
|
||||
// passing the name of the organization.
|
||||
//
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-post
|
||||
func (s *OrganizationService) CreateOrganizationWithContext(ctx context.Context, name string) (*Organization, *Response, error) {
|
||||
apiEndPoint := "rest/servicedeskapi/organization"
|
||||
|
||||
organization := OrganizationCreationDTO{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndPoint, organization)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
o := new(Organization)
|
||||
resp, err := s.client.Do(req, &o)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
|
||||
return o, resp, nil
|
||||
}
|
||||
|
||||
// CreateOrganization wraps CreateOrganizationWithContext using the background context.
|
||||
func (s *OrganizationService) CreateOrganization(name string) (*Organization, *Response, error) {
|
||||
return s.CreateOrganizationWithContext(context.Background(), name)
|
||||
}
|
||||
|
||||
// GetOrganizationWithContext returns details of an
|
||||
// organization. Use this method to get organization
|
||||
// details whenever your application component is
|
||||
// passed an organization ID but needs to display
|
||||
// other organization details.
|
||||
//
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-get
|
||||
func (s *OrganizationService) GetOrganizationWithContext(ctx context.Context, organizationID int) (*Organization, *Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d", organizationID)
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
o := new(Organization)
|
||||
resp, err := s.client.Do(req, &o)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
|
||||
return o, resp, nil
|
||||
}
|
||||
|
||||
// GetOrganization wraps GetOrganizationWithContext using the background context.
|
||||
func (s *OrganizationService) GetOrganization(organizationID int) (*Organization, *Response, error) {
|
||||
return s.GetOrganizationWithContext(context.Background(), organizationID)
|
||||
}
|
||||
|
||||
// DeleteOrganizationWithContext deletes an organization. Note that
|
||||
// the organization is deleted regardless
|
||||
// of other associations it may have.
|
||||
// For example, associations with service desks.
|
||||
//
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-delete
|
||||
// Caller must close resp.Body
|
||||
func (s *OrganizationService) DeleteOrganizationWithContext(ctx context.Context, organizationID int) (*Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d", organizationID)
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndPoint, nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return resp, jerr
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DeleteOrganization wraps DeleteOrganizationWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *OrganizationService) DeleteOrganization(organizationID int) (*Response, error) {
|
||||
return s.DeleteOrganizationWithContext(context.Background(), organizationID)
|
||||
}
|
||||
|
||||
// GetPropertiesKeysWithContext returns the keys of
|
||||
// all properties for an organization. Use this resource
|
||||
// when you need to find out what additional properties
|
||||
// items have been added to an organization.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-property-get
|
||||
func (s *OrganizationService) GetPropertiesKeysWithContext(ctx context.Context, organizationID int) (*PropertyKeys, *Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/property", organizationID)
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pk := new(PropertyKeys)
|
||||
resp, err := s.client.Do(req, &pk)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
|
||||
return pk, resp, nil
|
||||
}
|
||||
|
||||
// GetPropertiesKeys wraps GetPropertiesKeysWithContext using the background context.
|
||||
func (s *OrganizationService) GetPropertiesKeys(organizationID int) (*PropertyKeys, *Response, error) {
|
||||
return s.GetPropertiesKeysWithContext(context.Background(), organizationID)
|
||||
}
|
||||
|
||||
// GetPropertyWithContext returns the value of a property
|
||||
// from an organization. Use this method to obtain the JSON
|
||||
// content for an organization's property.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-property-propertykey-get
|
||||
func (s *OrganizationService) GetPropertyWithContext(ctx context.Context, organizationID int, propertyKey string) (*EntityProperty, *Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/property/%s", organizationID, propertyKey)
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
ep := new(EntityProperty)
|
||||
resp, err := s.client.Do(req, &ep)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
|
||||
return ep, resp, nil
|
||||
}
|
||||
|
||||
// GetProperty wraps GetPropertyWithContext using the background context.
|
||||
func (s *OrganizationService) GetProperty(organizationID int, propertyKey string) (*EntityProperty, *Response, error) {
|
||||
return s.GetPropertyWithContext(context.Background(), organizationID, propertyKey)
|
||||
}
|
||||
|
||||
// SetPropertyWithContext sets the value of a
|
||||
// property for an organization. Use this
|
||||
// resource to store custom data against an organization.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-property-propertykey-put
|
||||
// Caller must close resp.Body
|
||||
func (s *OrganizationService) SetPropertyWithContext(ctx context.Context, organizationID int, propertyKey string) (*Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/property/%s", organizationID, propertyKey)
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndPoint, nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return resp, jerr
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// SetProperty wraps SetPropertyWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *OrganizationService) SetProperty(organizationID int, propertyKey string) (*Response, error) {
|
||||
return s.SetPropertyWithContext(context.Background(), organizationID, propertyKey)
|
||||
}
|
||||
|
||||
// DeletePropertyWithContext removes a property from an organization.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-property-propertykey-delete
|
||||
// Caller must close resp.Body
|
||||
func (s *OrganizationService) DeletePropertyWithContext(ctx context.Context, organizationID int, propertyKey string) (*Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/property/%s", organizationID, propertyKey)
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndPoint, nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return resp, jerr
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DeleteProperty wraps DeletePropertyWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *OrganizationService) DeleteProperty(organizationID int, propertyKey string) (*Response, error) {
|
||||
return s.DeletePropertyWithContext(context.Background(), organizationID, propertyKey)
|
||||
}
|
||||
|
||||
// GetUsersWithContext returns all the users
|
||||
// associated with an organization. Use this
|
||||
// method where you want to provide a list of
|
||||
// users for an organization or determine if
|
||||
// a user is associated with an organization.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-user-get
|
||||
func (s *OrganizationService) GetUsersWithContext(ctx context.Context, organizationID int, start int, limit int) (*PagedDTO, *Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/user?start=%d&limit=%d", organizationID, start, limit)
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
users := new(PagedDTO)
|
||||
resp, err := s.client.Do(req, &users)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
|
||||
return users, resp, nil
|
||||
}
|
||||
|
||||
// GetUsers wraps GetUsersWithContext using the background context.
|
||||
func (s *OrganizationService) GetUsers(organizationID int, start int, limit int) (*PagedDTO, *Response, error) {
|
||||
return s.GetUsersWithContext(context.Background(), organizationID, start, limit)
|
||||
}
|
||||
|
||||
// AddUsersWithContext adds users to an organization.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-user-post
|
||||
// Caller must close resp.Body
|
||||
func (s *OrganizationService) AddUsersWithContext(ctx context.Context, organizationID int, users OrganizationUsersDTO) (*Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/user", organizationID)
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndPoint, users)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return resp, jerr
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// AddUsers wraps AddUsersWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *OrganizationService) AddUsers(organizationID int, users OrganizationUsersDTO) (*Response, error) {
|
||||
return s.AddUsersWithContext(context.Background(), organizationID, users)
|
||||
}
|
||||
|
||||
// RemoveUsersWithContext removes users from an organization.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-user-delete
|
||||
// Caller must close resp.Body
|
||||
func (s *OrganizationService) RemoveUsersWithContext(ctx context.Context, organizationID int, users OrganizationUsersDTO) (*Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/user", organizationID)
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndPoint, nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return resp, jerr
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// RemoveUsers wraps RemoveUsersWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *OrganizationService) RemoveUsers(organizationID int, users OrganizationUsersDTO) (*Response, error) {
|
||||
return s.RemoveUsersWithContext(context.Background(), organizationID, users)
|
||||
}
|
37
vendor/github.com/andygrunwald/go-jira/permissionscheme.go
generated
vendored
37
vendor/github.com/andygrunwald/go-jira/permissionscheme.go
generated
vendored
|
@ -1,10 +1,13 @@
|
|||
package jira
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// PermissionSchemeService handles permissionschemes for the JIRA instance / API.
|
||||
// PermissionSchemeService handles permissionschemes for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Permissionscheme
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Permissionscheme
|
||||
type PermissionSchemeService struct {
|
||||
client *Client
|
||||
}
|
||||
|
@ -25,12 +28,12 @@ type Holder struct {
|
|||
Expand string `json:"expand" structs:"expand"`
|
||||
}
|
||||
|
||||
// GetList returns a list of all permission schemes
|
||||
// GetListWithContext returns a list of all permission schemes
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-get
|
||||
func (s *PermissionSchemeService) GetList() (*PermissionSchemes, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-get
|
||||
func (s *PermissionSchemeService) GetListWithContext(ctx context.Context) (*PermissionSchemes, *Response, error) {
|
||||
apiEndpoint := "/rest/api/3/permissionscheme"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -45,12 +48,17 @@ func (s *PermissionSchemeService) GetList() (*PermissionSchemes, *Response, erro
|
|||
return pss, resp, nil
|
||||
}
|
||||
|
||||
// Get returns a full representation of the permission scheme for the schemeID
|
||||
// GetList wraps GetListWithContext using the background context.
|
||||
func (s *PermissionSchemeService) GetList() (*PermissionSchemes, *Response, error) {
|
||||
return s.GetListWithContext(context.Background())
|
||||
}
|
||||
|
||||
// GetWithContext returns a full representation of the permission scheme for the schemeID
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-schemeId-get
|
||||
func (s *PermissionSchemeService) Get(schemeID int) (*PermissionScheme, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-schemeId-get
|
||||
func (s *PermissionSchemeService) GetWithContext(ctx context.Context, schemeID int) (*PermissionScheme, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/3/permissionscheme/%d", schemeID)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -62,8 +70,13 @@ func (s *PermissionSchemeService) Get(schemeID int) (*PermissionScheme, *Respons
|
|||
return nil, resp, jerr
|
||||
}
|
||||
if ps.Self == "" {
|
||||
return nil, resp, fmt.Errorf("No permissionscheme with ID %d found", schemeID)
|
||||
return nil, resp, fmt.Errorf("no permissionscheme with ID %d found", schemeID)
|
||||
}
|
||||
|
||||
return ps, resp, nil
|
||||
}
|
||||
|
||||
// Get wraps GetWithContext using the background context.
|
||||
func (s *PermissionSchemeService) Get(schemeID int) (*PermissionScheme, *Response, error) {
|
||||
return s.GetWithContext(context.Background(), schemeID)
|
||||
}
|
||||
|
|
21
vendor/github.com/andygrunwald/go-jira/priority.go
generated
vendored
21
vendor/github.com/andygrunwald/go-jira/priority.go
generated
vendored
|
@ -1,13 +1,15 @@
|
|||
package jira
|
||||
|
||||
// PriorityService handles priorities for the JIRA instance / API.
|
||||
import "context"
|
||||
|
||||
// PriorityService handles priorities for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Priority
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Priority
|
||||
type PriorityService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Priority represents a priority of a JIRA issue.
|
||||
// Priority represents a priority of a Jira issue.
|
||||
// Typical types are "Normal", "Moderate", "Urgent", ...
|
||||
type Priority struct {
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
|
@ -18,12 +20,12 @@ type Priority struct {
|
|||
Description string `json:"description,omitempty" structs:"description,omitempty"`
|
||||
}
|
||||
|
||||
// GetList gets all priorities from JIRA
|
||||
// GetListWithContext gets all priorities from Jira
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-priority-get
|
||||
func (s *PriorityService) GetList() ([]Priority, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-priority-get
|
||||
func (s *PriorityService) GetListWithContext(ctx context.Context) ([]Priority, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/priority"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -35,3 +37,8 @@ func (s *PriorityService) GetList() ([]Priority, *Response, error) {
|
|||
}
|
||||
return priorityList, resp, nil
|
||||
}
|
||||
|
||||
// GetList wraps GetListWithContext using the background context.
|
||||
func (s *PriorityService) GetList() ([]Priority, *Response, error) {
|
||||
return s.GetListWithContext(context.Background())
|
||||
}
|
||||
|
|
63
vendor/github.com/andygrunwald/go-jira/project.go
generated
vendored
63
vendor/github.com/andygrunwald/go-jira/project.go
generated
vendored
|
@ -1,14 +1,15 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-querystring/query"
|
||||
)
|
||||
|
||||
// ProjectService handles projects for the JIRA instance / API.
|
||||
// ProjectService handles projects for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project
|
||||
type ProjectService struct {
|
||||
client *Client
|
||||
}
|
||||
|
@ -34,7 +35,7 @@ type ProjectCategory struct {
|
|||
Description string `json:"description" structs:"description,omitempty"`
|
||||
}
|
||||
|
||||
// Project represents a JIRA Project.
|
||||
// Project represents a Jira Project.
|
||||
type Project struct {
|
||||
Expand string `json:"expand,omitempty" structs:"expand,omitempty"`
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
|
@ -80,20 +81,25 @@ type PermissionScheme struct {
|
|||
Permissions []Permission `json:"permissions" structs:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
// GetList gets all projects form JIRA
|
||||
// GetListWithContext gets all projects form Jira
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getAllProjects
|
||||
func (s *ProjectService) GetList() (*ProjectList, *Response, error) {
|
||||
return s.ListWithOptions(&GetQueryOptions{})
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getAllProjects
|
||||
func (s *ProjectService) GetListWithContext(ctx context.Context) (*ProjectList, *Response, error) {
|
||||
return s.ListWithOptionsWithContext(ctx, &GetQueryOptions{})
|
||||
}
|
||||
|
||||
// ListWithOptions gets all projects form JIRA with optional query params, like &GetQueryOptions{Expand: "issueTypes"} to get
|
||||
// GetList wraps GetListWithContext using the background context.
|
||||
func (s *ProjectService) GetList() (*ProjectList, *Response, error) {
|
||||
return s.GetListWithContext(context.Background())
|
||||
}
|
||||
|
||||
// ListWithOptionsWithContext gets all projects form Jira with optional query params, like &GetQueryOptions{Expand: "issueTypes"} to get
|
||||
// a list of all projects and their supported issuetypes
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getAllProjects
|
||||
func (s *ProjectService) ListWithOptions(options *GetQueryOptions) (*ProjectList, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getAllProjects
|
||||
func (s *ProjectService) ListWithOptionsWithContext(ctx context.Context, options *GetQueryOptions) (*ProjectList, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/project"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -116,14 +122,19 @@ func (s *ProjectService) ListWithOptions(options *GetQueryOptions) (*ProjectList
|
|||
return projectList, resp, nil
|
||||
}
|
||||
|
||||
// Get returns a full representation of the project for the given issue key.
|
||||
// JIRA will attempt to identify the project by the projectIdOrKey path parameter.
|
||||
// ListWithOptions wraps ListWithOptionsWithContext using the background context.
|
||||
func (s *ProjectService) ListWithOptions(options *GetQueryOptions) (*ProjectList, *Response, error) {
|
||||
return s.ListWithOptionsWithContext(context.Background(), options)
|
||||
}
|
||||
|
||||
// GetWithContext returns a full representation of the project for the given issue key.
|
||||
// Jira will attempt to identify the project by the projectIdOrKey path parameter.
|
||||
// This can be an project id, or an project key.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getProject
|
||||
func (s *ProjectService) Get(projectID string) (*Project, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getProject
|
||||
func (s *ProjectService) GetWithContext(ctx context.Context, projectID string) (*Project, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/api/2/project/%s", projectID)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -138,14 +149,19 @@ func (s *ProjectService) Get(projectID string) (*Project, *Response, error) {
|
|||
return project, resp, nil
|
||||
}
|
||||
|
||||
// GetPermissionScheme returns a full representation of the permission scheme for the project
|
||||
// JIRA will attempt to identify the project by the projectIdOrKey path parameter.
|
||||
// Get wraps GetWithContext using the background context.
|
||||
func (s *ProjectService) Get(projectID string) (*Project, *Response, error) {
|
||||
return s.GetWithContext(context.Background(), projectID)
|
||||
}
|
||||
|
||||
// GetPermissionSchemeWithContext returns a full representation of the permission scheme for the project
|
||||
// Jira will attempt to identify the project by the projectIdOrKey path parameter.
|
||||
// This can be an project id, or an project key.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getProject
|
||||
func (s *ProjectService) GetPermissionScheme(projectID string) (*PermissionScheme, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getProject
|
||||
func (s *ProjectService) GetPermissionSchemeWithContext(ctx context.Context, projectID string) (*PermissionScheme, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/project/%s/permissionscheme", projectID)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -159,3 +175,8 @@ func (s *ProjectService) GetPermissionScheme(projectID string) (*PermissionSchem
|
|||
|
||||
return ps, resp, nil
|
||||
}
|
||||
|
||||
// GetPermissionScheme wraps GetPermissionSchemeWithContext using the background context.
|
||||
func (s *ProjectService) GetPermissionScheme(projectID string) (*PermissionScheme, *Response, error) {
|
||||
return s.GetPermissionSchemeWithContext(context.Background(), projectID)
|
||||
}
|
||||
|
|
123
vendor/github.com/andygrunwald/go-jira/request.go
generated
vendored
Normal file
123
vendor/github.com/andygrunwald/go-jira/request.go
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// RequestService handles ServiceDesk customer requests for the Jira instance / API.
|
||||
type RequestService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Request represents a ServiceDesk customer request.
|
||||
type Request struct {
|
||||
IssueID string `json:"issueId,omitempty" structs:"issueId,omitempty"`
|
||||
IssueKey string `json:"issueKey,omitempty" structs:"issueKey,omitempty"`
|
||||
TypeID string `json:"requestTypeId,omitempty" structs:"requestTypeId,omitempty"`
|
||||
ServiceDeskID string `json:"serviceDeskId,omitempty" structs:"serviceDeskId,omitempty"`
|
||||
Reporter *Customer `json:"reporter,omitempty" structs:"reporter,omitempty"`
|
||||
FieldValues []RequestFieldValue `json:"requestFieldValues,omitempty" structs:"requestFieldValues,omitempty"`
|
||||
Status *RequestStatus `json:"currentStatus,omitempty" structs:"currentStatus,omitempty"`
|
||||
Links *SelfLink `json:"_links,omitempty" structs:"_links,omitempty"`
|
||||
Expands []string `json:"_expands,omitempty" structs:"_expands,omitempty"`
|
||||
}
|
||||
|
||||
// RequestFieldValue is a request field.
|
||||
type RequestFieldValue struct {
|
||||
FieldID string `json:"fieldId,omitempty" structs:"fieldId,omitempty"`
|
||||
Label string `json:"label,omitempty" structs:"label,omitempty"`
|
||||
Value string `json:"value,omitempty" structs:"value,omitempty"`
|
||||
}
|
||||
|
||||
// RequestDate is the date format used in requests.
|
||||
type RequestDate struct {
|
||||
ISO8601 string `json:"iso8601,omitempty" structs:"iso8601,omitempty"`
|
||||
Jira string `json:"jira,omitempty" structs:"jira,omitempty"`
|
||||
Friendly string `json:"friendly,omitempty" structs:"friendly,omitempty"`
|
||||
Epoch int64 `json:"epoch,omitempty" structs:"epoch,omitempty"`
|
||||
}
|
||||
|
||||
// RequestStatus is the status for a request.
|
||||
type RequestStatus struct {
|
||||
Status string
|
||||
Category string
|
||||
Date RequestDate
|
||||
}
|
||||
|
||||
// RequestComment is a comment for a request.
|
||||
type RequestComment struct {
|
||||
ID string `json:"id,omitempty" structs:"id,omitempty"`
|
||||
Body string `json:"body,omitempty" structs:"body,omitempty"`
|
||||
Public bool `json:"public" structs:"public"`
|
||||
Author *Customer `json:"author,omitempty" structs:"author,omitempty"`
|
||||
Created *RequestDate `json:"created,omitempty" structs:"created,omitempty"`
|
||||
Links *SelfLink `json:"_links,omitempty" structs:"_links,omitempty"`
|
||||
Expands []string `json:"_expands,omitempty" structs:"_expands,omitempty"`
|
||||
}
|
||||
|
||||
// CreateWithContext creates a new request.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-request/#api-rest-servicedeskapi-request-post
|
||||
func (r *RequestService) CreateWithContext(ctx context.Context, requester string, participants []string, request *Request) (*Request, *Response, error) {
|
||||
apiEndpoint := "rest/servicedeskapi/request"
|
||||
|
||||
payload := struct {
|
||||
*Request
|
||||
FieldValues map[string]string `json:"requestFieldValues,omitempty"`
|
||||
Requester string `json:"raiseOnBehalfOf,omitempty"`
|
||||
Participants []string `json:"requestParticipants,omitempty"`
|
||||
}{
|
||||
Request: request,
|
||||
FieldValues: make(map[string]string),
|
||||
Requester: requester,
|
||||
Participants: participants,
|
||||
}
|
||||
|
||||
for _, field := range request.FieldValues {
|
||||
payload.FieldValues[field.FieldID] = field.Value
|
||||
}
|
||||
|
||||
req, err := r.client.NewRequestWithContext(ctx, "POST", apiEndpoint, payload)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
responseRequest := new(Request)
|
||||
resp, err := r.client.Do(req, responseRequest)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
|
||||
return responseRequest, resp, nil
|
||||
}
|
||||
|
||||
// Create wraps CreateWithContext using the background context.
|
||||
func (r *RequestService) Create(requester string, participants []string, request *Request) (*Request, *Response, error) {
|
||||
return r.CreateWithContext(context.Background(), requester, participants, request)
|
||||
}
|
||||
|
||||
// CreateCommentWithContext creates a comment on a request.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-request/#api-rest-servicedeskapi-request-issueidorkey-comment-post
|
||||
func (r *RequestService) CreateCommentWithContext(ctx context.Context, issueIDOrKey string, comment *RequestComment) (*RequestComment, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/servicedeskapi/request/%v/comment", issueIDOrKey)
|
||||
|
||||
req, err := r.client.NewRequestWithContext(ctx, "POST", apiEndpoint, comment)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
responseComment := new(RequestComment)
|
||||
resp, err := r.client.Do(req, responseComment)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
|
||||
return responseComment, resp, nil
|
||||
}
|
||||
|
||||
// CreateComment wraps CreateCommentWithContext using the background context.
|
||||
func (r *RequestService) CreateComment(issueIDOrKey string, comment *RequestComment) (*RequestComment, *Response, error) {
|
||||
return r.CreateCommentWithContext(context.Background(), issueIDOrKey, comment)
|
||||
}
|
24
vendor/github.com/andygrunwald/go-jira/request_context.go
generated
vendored
Normal file
24
vendor/github.com/andygrunwald/go-jira/request_context.go
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
//go:build go1.13
|
||||
// +build go1.13
|
||||
|
||||
// This file provides glue to use Context in `http.Request` with
|
||||
// Go version 1.13 and higher.
|
||||
|
||||
// The function `http.NewRequestWithContext` has been added in Go 1.13.
|
||||
// Before the release 1.13, to use Context we need creat `http.Request`
|
||||
// then use the method `WithContext` to create a new `http.Request`
|
||||
// with Context from the existing `http.Request`.
|
||||
//
|
||||
// Doc: https://golang.org/doc/go1.13#net/http
|
||||
|
||||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func newRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*http.Request, error) {
|
||||
return http.NewRequestWithContext(ctx, method, url, body)
|
||||
}
|
29
vendor/github.com/andygrunwald/go-jira/request_legacy.go
generated
vendored
Normal file
29
vendor/github.com/andygrunwald/go-jira/request_legacy.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
//go:build !go1.13
|
||||
// +build !go1.13
|
||||
|
||||
// This file provides glue to use Context in `http.Request` with
|
||||
// Go version before 1.13.
|
||||
|
||||
// The function `http.NewRequestWithContext` has been added in Go 1.13.
|
||||
// Before the release 1.13, to use Context we need creat `http.Request`
|
||||
// then use the method `WithContext` to create a new `http.Request`
|
||||
// with Context from the existing `http.Request`.
|
||||
//
|
||||
// Doc: https://golang.org/doc/go1.13#net/http
|
||||
|
||||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func newRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*http.Request, error) {
|
||||
r, err := http.NewRequest(method, url, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r.WithContext(ctx), nil
|
||||
}
|
21
vendor/github.com/andygrunwald/go-jira/resolution.go
generated
vendored
21
vendor/github.com/andygrunwald/go-jira/resolution.go
generated
vendored
|
@ -1,13 +1,15 @@
|
|||
package jira
|
||||
|
||||
// ResolutionService handles resolutions for the JIRA instance / API.
|
||||
import "context"
|
||||
|
||||
// ResolutionService handles resolutions for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Resolution
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Resolution
|
||||
type ResolutionService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Resolution represents a resolution of a JIRA issue.
|
||||
// Resolution represents a resolution of a Jira issue.
|
||||
// Typical types are "Fixed", "Suspended", "Won't Fix", ...
|
||||
type Resolution struct {
|
||||
Self string `json:"self" structs:"self"`
|
||||
|
@ -16,12 +18,12 @@ type Resolution struct {
|
|||
Name string `json:"name" structs:"name"`
|
||||
}
|
||||
|
||||
// GetList gets all resolutions from JIRA
|
||||
// GetListWithContext gets all resolutions from Jira
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-resolution-get
|
||||
func (s *ResolutionService) GetList() ([]Resolution, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-resolution-get
|
||||
func (s *ResolutionService) GetListWithContext(ctx context.Context) ([]Resolution, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/resolution"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -33,3 +35,8 @@ func (s *ResolutionService) GetList() ([]Resolution, *Response, error) {
|
|||
}
|
||||
return resolutionList, resp, nil
|
||||
}
|
||||
|
||||
// GetList wraps GetListWithContext using the background context.
|
||||
func (s *ResolutionService) GetList() ([]Resolution, *Response, error) {
|
||||
return s.GetListWithContext(context.Background())
|
||||
}
|
||||
|
|
37
vendor/github.com/andygrunwald/go-jira/role.go
generated
vendored
37
vendor/github.com/andygrunwald/go-jira/role.go
generated
vendored
|
@ -1,17 +1,18 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// RoleService handles roles for the JIRA instance / API.
|
||||
// RoleService handles roles for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Role
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Role
|
||||
type RoleService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Role represents a JIRA product role
|
||||
// Role represents a Jira product role
|
||||
type Role struct {
|
||||
Self string `json:"self" structs:"self"`
|
||||
Name string `json:"name" structs:"name"`
|
||||
|
@ -20,7 +21,7 @@ type Role struct {
|
|||
Actors []*Actor `json:"actors" structs:"actors"`
|
||||
}
|
||||
|
||||
// Actor represents a JIRA actor
|
||||
// Actor represents a Jira actor
|
||||
type Actor struct {
|
||||
ID int `json:"id" structs:"id"`
|
||||
DisplayName string `json:"displayName" structs:"displayName"`
|
||||
|
@ -35,12 +36,12 @@ type ActorUser struct {
|
|||
AccountID string `json:"accountId" structs:"accountId"`
|
||||
}
|
||||
|
||||
// GetList returns a list of all available project roles
|
||||
// GetListWithContext returns a list of all available project roles
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-get
|
||||
func (s *RoleService) GetList() (*[]Role, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-get
|
||||
func (s *RoleService) GetListWithContext(ctx context.Context) (*[]Role, *Response, error) {
|
||||
apiEndpoint := "rest/api/3/role"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -53,12 +54,17 @@ func (s *RoleService) GetList() (*[]Role, *Response, error) {
|
|||
return roles, resp, err
|
||||
}
|
||||
|
||||
// Get retreives a single Role from Jira
|
||||
// GetList wraps GetListWithContext using the background context.
|
||||
func (s *RoleService) GetList() (*[]Role, *Response, error) {
|
||||
return s.GetListWithContext(context.Background())
|
||||
}
|
||||
|
||||
// GetWithContext retreives a single Role from Jira
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-id-get
|
||||
func (s *RoleService) Get(roleID int) (*Role, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-id-get
|
||||
func (s *RoleService) GetWithContext(ctx context.Context, roleID int) (*Role, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/api/3/role/%d", roleID)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -69,8 +75,13 @@ func (s *RoleService) Get(roleID int) (*Role, *Response, error) {
|
|||
return nil, resp, jerr
|
||||
}
|
||||
if role.Self == "" {
|
||||
return nil, resp, fmt.Errorf("No role with ID %d found", roleID)
|
||||
return nil, resp, fmt.Errorf("no role with ID %d found", roleID)
|
||||
}
|
||||
|
||||
return role, resp, err
|
||||
}
|
||||
|
||||
// Get wraps GetWithContext using the background context.
|
||||
func (s *RoleService) Get(roleID int) (*Role, *Response, error) {
|
||||
return s.GetWithContext(context.Background(), roleID)
|
||||
}
|
||||
|
|
227
vendor/github.com/andygrunwald/go-jira/servicedesk.go
generated
vendored
Normal file
227
vendor/github.com/andygrunwald/go-jira/servicedesk.go
generated
vendored
Normal file
|
@ -0,0 +1,227 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/google/go-querystring/query"
|
||||
)
|
||||
|
||||
// ServiceDeskService handles ServiceDesk for the Jira instance / API.
|
||||
type ServiceDeskService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// ServiceDeskOrganizationDTO is a DTO for ServiceDesk organizations
|
||||
type ServiceDeskOrganizationDTO struct {
|
||||
OrganizationID int `json:"organizationId,omitempty" structs:"organizationId,omitempty"`
|
||||
}
|
||||
|
||||
// GetOrganizationsWithContext returns a list of
|
||||
// all organizations associated with a service desk.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-servicedesk-servicedeskid-organization-get
|
||||
func (s *ServiceDeskService) GetOrganizationsWithContext(ctx context.Context, serviceDeskID interface{}, start int, limit int, accountID string) (*PagedDTO, *Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/organization?start=%d&limit=%d", serviceDeskID, start, limit)
|
||||
if accountID != "" {
|
||||
apiEndPoint += fmt.Sprintf("&accountId=%s", accountID)
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
orgs := new(PagedDTO)
|
||||
resp, err := s.client.Do(req, &orgs)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
|
||||
return orgs, resp, nil
|
||||
}
|
||||
|
||||
// GetOrganizations wraps GetOrganizationsWithContext using the background context.
|
||||
func (s *ServiceDeskService) GetOrganizations(serviceDeskID interface{}, start int, limit int, accountID string) (*PagedDTO, *Response, error) {
|
||||
return s.GetOrganizationsWithContext(context.Background(), serviceDeskID, start, limit, accountID)
|
||||
}
|
||||
|
||||
// AddOrganizationWithContext adds an organization to
|
||||
// a service desk. If the organization ID is already
|
||||
// associated with the service desk, no change is made
|
||||
// and the resource returns a 204 success code.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-servicedesk-servicedeskid-organization-post
|
||||
// Caller must close resp.Body
|
||||
func (s *ServiceDeskService) AddOrganizationWithContext(ctx context.Context, serviceDeskID interface{}, organizationID int) (*Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/organization", serviceDeskID)
|
||||
|
||||
organization := ServiceDeskOrganizationDTO{
|
||||
OrganizationID: organizationID,
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndPoint, organization)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return resp, jerr
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// AddOrganization wraps AddOrganizationWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *ServiceDeskService) AddOrganization(serviceDeskID interface{}, organizationID int) (*Response, error) {
|
||||
return s.AddOrganizationWithContext(context.Background(), serviceDeskID, organizationID)
|
||||
}
|
||||
|
||||
// RemoveOrganizationWithContext removes an organization
|
||||
// from a service desk. If the organization ID does not
|
||||
// match an organization associated with the service desk,
|
||||
// no change is made and the resource returns a 204 success code.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-servicedesk-servicedeskid-organization-delete
|
||||
// Caller must close resp.Body
|
||||
func (s *ServiceDeskService) RemoveOrganizationWithContext(ctx context.Context, serviceDeskID interface{}, organizationID int) (*Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/organization", serviceDeskID)
|
||||
|
||||
organization := ServiceDeskOrganizationDTO{
|
||||
OrganizationID: organizationID,
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndPoint, organization)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return resp, jerr
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// RemoveOrganization wraps RemoveOrganizationWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *ServiceDeskService) RemoveOrganization(serviceDeskID interface{}, organizationID int) (*Response, error) {
|
||||
return s.RemoveOrganizationWithContext(context.Background(), serviceDeskID, organizationID)
|
||||
}
|
||||
|
||||
// AddCustomersWithContext adds customers to the given service desk.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-servicedesk/#api-rest-servicedeskapi-servicedesk-servicedeskid-customer-post
|
||||
func (s *ServiceDeskService) AddCustomersWithContext(ctx context.Context, serviceDeskID interface{}, acountIDs ...string) (*Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/customer", serviceDeskID)
|
||||
|
||||
payload := struct {
|
||||
AccountIDs []string `json:"accountIds"`
|
||||
}{
|
||||
AccountIDs: acountIDs,
|
||||
}
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
return resp, NewJiraError(resp, err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
_, _ = io.Copy(ioutil.Discard, resp.Body)
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// AddCustomers wraps AddCustomersWithContext using the background context.
|
||||
func (s *ServiceDeskService) AddCustomers(serviceDeskID interface{}, acountIDs ...string) (*Response, error) {
|
||||
return s.AddCustomersWithContext(context.Background(), serviceDeskID, acountIDs...)
|
||||
}
|
||||
|
||||
// RemoveCustomersWithContext removes customers to the given service desk.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-servicedesk/#api-rest-servicedeskapi-servicedesk-servicedeskid-customer-delete
|
||||
func (s *ServiceDeskService) RemoveCustomersWithContext(ctx context.Context, serviceDeskID interface{}, acountIDs ...string) (*Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/customer", serviceDeskID)
|
||||
|
||||
payload := struct {
|
||||
AccountIDs []string `json:"accountIDs"`
|
||||
}{
|
||||
AccountIDs: acountIDs,
|
||||
}
|
||||
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
return resp, NewJiraError(resp, err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
_, _ = io.Copy(ioutil.Discard, resp.Body)
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// RemoveCustomers wraps RemoveCustomersWithContext using the background context.
|
||||
func (s *ServiceDeskService) RemoveCustomers(serviceDeskID interface{}, acountIDs ...string) (*Response, error) {
|
||||
return s.RemoveCustomersWithContext(context.Background(), serviceDeskID, acountIDs...)
|
||||
}
|
||||
|
||||
// ListCustomersWithContext lists customers for a ServiceDesk.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-servicedesk/#api-rest-servicedeskapi-servicedesk-servicedeskid-customer-get
|
||||
func (s *ServiceDeskService) ListCustomersWithContext(ctx context.Context, serviceDeskID interface{}, options *CustomerListOptions) (*CustomerList, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/customer", serviceDeskID)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// this is an experiemntal endpoint
|
||||
req.Header.Set("X-ExperimentalApi", "opt-in")
|
||||
|
||||
if options != nil {
|
||||
q, err := query.Values(options)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
customerList := new(CustomerList)
|
||||
if err := json.NewDecoder(resp.Body).Decode(customerList); err != nil {
|
||||
return nil, resp, fmt.Errorf("could not unmarshall the data into struct")
|
||||
}
|
||||
|
||||
return customerList, resp, nil
|
||||
}
|
||||
|
||||
// ListCustomers wraps ListCustomersWithContext using the background context.
|
||||
func (s *ServiceDeskService) ListCustomers(serviceDeskID interface{}, options *CustomerListOptions) (*CustomerList, *Response, error) {
|
||||
return s.ListCustomersWithContext(context.Background(), serviceDeskID, options)
|
||||
}
|
48
vendor/github.com/andygrunwald/go-jira/sprint.go
generated
vendored
48
vendor/github.com/andygrunwald/go-jira/sprint.go
generated
vendored
|
@ -1,12 +1,13 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-querystring/query"
|
||||
)
|
||||
|
||||
// SprintService handles sprints in JIRA Agile API.
|
||||
// SprintService handles sprints in Jira Agile API.
|
||||
// See https://docs.atlassian.com/jira-software/REST/cloud/
|
||||
type SprintService struct {
|
||||
client *Client
|
||||
|
@ -22,17 +23,18 @@ type IssuesInSprintResult struct {
|
|||
Issues []Issue `json:"issues"`
|
||||
}
|
||||
|
||||
// MoveIssuesToSprint moves issues to a sprint, for a given sprint Id.
|
||||
// MoveIssuesToSprintWithContext moves issues to a sprint, for a given sprint Id.
|
||||
// Issues can only be moved to open or active sprints.
|
||||
// The maximum number of issues that can be moved in one operation is 50.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/sprint-moveIssuesToSprint
|
||||
func (s *SprintService) MoveIssuesToSprint(sprintID int, issueIDs []string) (*Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/sprint-moveIssuesToSprint
|
||||
// Caller must close resp.Body
|
||||
func (s *SprintService) MoveIssuesToSprintWithContext(ctx context.Context, sprintID int, issueIDs []string) (*Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/agile/1.0/sprint/%d/issue", sprintID)
|
||||
|
||||
payload := IssuesWrapper{Issues: issueIDs}
|
||||
|
||||
req, err := s.client.NewRequest("POST", apiEndpoint, payload)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, payload)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -45,15 +47,21 @@ func (s *SprintService) MoveIssuesToSprint(sprintID int, issueIDs []string) (*Re
|
|||
return resp, err
|
||||
}
|
||||
|
||||
// GetIssuesForSprint returns all issues in a sprint, for a given sprint Id.
|
||||
// MoveIssuesToSprint wraps MoveIssuesToSprintWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *SprintService) MoveIssuesToSprint(sprintID int, issueIDs []string) (*Response, error) {
|
||||
return s.MoveIssuesToSprintWithContext(context.Background(), sprintID, issueIDs)
|
||||
}
|
||||
|
||||
// GetIssuesForSprintWithContext returns all issues in a sprint, for a given sprint Id.
|
||||
// This only includes issues that the user has permission to view.
|
||||
// By default, the returned issues are ordered by rank.
|
||||
//
|
||||
// JIRA API Docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/sprint-getIssuesForSprint
|
||||
func (s *SprintService) GetIssuesForSprint(sprintID int) ([]Issue, *Response, error) {
|
||||
// Jira API Docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/sprint-getIssuesForSprint
|
||||
func (s *SprintService) GetIssuesForSprintWithContext(ctx context.Context, sprintID int) ([]Issue, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/agile/1.0/sprint/%d/issue", sprintID)
|
||||
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -68,20 +76,25 @@ func (s *SprintService) GetIssuesForSprint(sprintID int) ([]Issue, *Response, er
|
|||
return result.Issues, resp, err
|
||||
}
|
||||
|
||||
// GetIssue returns a full representation of the issue for the given issue key.
|
||||
// JIRA will attempt to identify the issue by the issueIdOrKey path parameter.
|
||||
// GetIssuesForSprint wraps GetIssuesForSprintWithContext using the background context.
|
||||
func (s *SprintService) GetIssuesForSprint(sprintID int) ([]Issue, *Response, error) {
|
||||
return s.GetIssuesForSprintWithContext(context.Background(), sprintID)
|
||||
}
|
||||
|
||||
// GetIssueWithContext returns a full representation of the issue for the given issue key.
|
||||
// Jira will attempt to identify the issue by the issueIdOrKey path parameter.
|
||||
// This can be an issue id, or an issue key.
|
||||
// If the issue cannot be found via an exact match, JIRA will also look for the issue in a case-insensitive way, or by looking to see if the issue was moved.
|
||||
// If the issue cannot be found via an exact match, Jira will also look for the issue in a case-insensitive way, or by looking to see if the issue was moved.
|
||||
//
|
||||
// The given options will be appended to the query string
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/7.3.1/#agile/1.0/issue-getIssue
|
||||
// Jira API docs: https://docs.atlassian.com/jira-software/REST/7.3.1/#agile/1.0/issue-getIssue
|
||||
//
|
||||
// TODO: create agile service for holding all agile apis' implementation
|
||||
func (s *SprintService) GetIssue(issueID string, options *GetQueryOptions) (*Issue, *Response, error) {
|
||||
func (s *SprintService) GetIssueWithContext(ctx context.Context, issueID string, options *GetQueryOptions) (*Issue, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/agile/1.0/issue/%s", issueID)
|
||||
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -105,3 +118,8 @@ func (s *SprintService) GetIssue(issueID string, options *GetQueryOptions) (*Iss
|
|||
|
||||
return issue, resp, nil
|
||||
}
|
||||
|
||||
// GetIssue wraps GetIssueWithContext using the background context.
|
||||
func (s *SprintService) GetIssue(issueID string, options *GetQueryOptions) (*Issue, *Response, error) {
|
||||
return s.GetIssueWithContext(context.Background(), issueID, options)
|
||||
}
|
||||
|
|
23
vendor/github.com/andygrunwald/go-jira/status.go
generated
vendored
23
vendor/github.com/andygrunwald/go-jira/status.go
generated
vendored
|
@ -1,15 +1,17 @@
|
|||
package jira
|
||||
|
||||
// StatusService handles staties for the JIRA instance / API.
|
||||
import "context"
|
||||
|
||||
// StatusService handles staties for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Workflow-statuses
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Workflow-statuses
|
||||
type StatusService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Status represents the current status of a JIRA issue.
|
||||
// Status represents the current status of a Jira issue.
|
||||
// Typical status are "Open", "In Progress", "Closed", ...
|
||||
// Status can be user defined in every JIRA instance.
|
||||
// Status can be user defined in every Jira instance.
|
||||
type Status struct {
|
||||
Self string `json:"self" structs:"self"`
|
||||
Description string `json:"description" structs:"description"`
|
||||
|
@ -19,12 +21,12 @@ type Status struct {
|
|||
StatusCategory StatusCategory `json:"statusCategory" structs:"statusCategory"`
|
||||
}
|
||||
|
||||
// GetAllStatuses returns a list of all statuses associated with workflows.
|
||||
// GetAllStatusesWithContext returns a list of all statuses associated with workflows.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-status-get
|
||||
func (s *StatusService) GetAllStatuses() ([]Status, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-status-get
|
||||
func (s *StatusService) GetAllStatusesWithContext(ctx context.Context) ([]Status, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/status"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -38,3 +40,8 @@ func (s *StatusService) GetAllStatuses() ([]Status, *Response, error) {
|
|||
|
||||
return statusList, resp, nil
|
||||
}
|
||||
|
||||
// GetAllStatuses wraps GetAllStatusesWithContext using the background context.
|
||||
func (s *StatusService) GetAllStatuses() ([]Status, *Response, error) {
|
||||
return s.GetAllStatusesWithContext(context.Background())
|
||||
}
|
||||
|
|
23
vendor/github.com/andygrunwald/go-jira/statuscategory.go
generated
vendored
23
vendor/github.com/andygrunwald/go-jira/statuscategory.go
generated
vendored
|
@ -1,14 +1,16 @@
|
|||
package jira
|
||||
|
||||
// StatusCategoryService handles status categories for the JIRA instance / API.
|
||||
import "context"
|
||||
|
||||
// StatusCategoryService handles status categories for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Statuscategory
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Statuscategory
|
||||
type StatusCategoryService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// StatusCategory represents the category a status belongs to.
|
||||
// Those categories can be user defined in every JIRA instance.
|
||||
// Those categories can be user defined in every Jira instance.
|
||||
type StatusCategory struct {
|
||||
Self string `json:"self" structs:"self"`
|
||||
ID int `json:"id" structs:"id"`
|
||||
|
@ -17,7 +19,7 @@ type StatusCategory struct {
|
|||
ColorName string `json:"colorName" structs:"colorName"`
|
||||
}
|
||||
|
||||
// These constants are the keys of the default JIRA status categories
|
||||
// These constants are the keys of the default Jira status categories
|
||||
const (
|
||||
StatusCategoryComplete = "done"
|
||||
StatusCategoryInProgress = "indeterminate"
|
||||
|
@ -25,12 +27,12 @@ const (
|
|||
StatusCategoryUndefined = "undefined"
|
||||
)
|
||||
|
||||
// GetList gets all status categories from JIRA
|
||||
// GetListWithContext gets all status categories from Jira
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-statuscategory-get
|
||||
func (s *StatusCategoryService) GetList() ([]StatusCategory, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-statuscategory-get
|
||||
func (s *StatusCategoryService) GetListWithContext(ctx context.Context) ([]StatusCategory, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/statuscategory"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -42,3 +44,8 @@ func (s *StatusCategoryService) GetList() ([]StatusCategory, *Response, error) {
|
|||
}
|
||||
return statusCategoryList, resp, nil
|
||||
}
|
||||
|
||||
// GetList wraps GetListWithContext using the background context.
|
||||
func (s *StatusCategoryService) GetList() ([]StatusCategory, *Response, error) {
|
||||
return s.GetListWithContext(context.Background())
|
||||
}
|
||||
|
|
9
vendor/github.com/andygrunwald/go-jira/types.go
generated
vendored
Normal file
9
vendor/github.com/andygrunwald/go-jira/types.go
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
package jira
|
||||
|
||||
// Bool is a helper routine that allocates a new bool value
|
||||
// to store v and returns a pointer to it.
|
||||
func Bool(v bool) *bool {
|
||||
p := new(bool)
|
||||
*p = v
|
||||
return p
|
||||
}
|
157
vendor/github.com/andygrunwald/go-jira/user.go
generated
vendored
157
vendor/github.com/andygrunwald/go-jira/user.go
generated
vendored
|
@ -1,25 +1,24 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// UserService handles users for the JIRA instance / API.
|
||||
// UserService handles users for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Users
|
||||
type UserService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// User represents a JIRA user.
|
||||
// User represents a Jira user.
|
||||
type User struct {
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"`
|
||||
AccountType string `json:"accountType,omitempty" structs:"accountType,omitempty"`
|
||||
// TODO: name & key are deprecated, see:
|
||||
// https://developer.atlassian.com/cloud/jira/platform/api-changes-for-user-privacy-announcement/
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"`
|
||||
AccountType string `json:"accountType,omitempty" structs:"accountType,omitempty"`
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
Key string `json:"key,omitempty" structs:"key,omitempty"`
|
||||
Password string `json:"-"`
|
||||
|
@ -47,12 +46,12 @@ type userSearch []userSearchParam
|
|||
|
||||
type userSearchF func(userSearch) userSearch
|
||||
|
||||
// Get gets user info from JIRA
|
||||
// GetWithContext gets user info from Jira using its Account Id
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUser
|
||||
func (s *UserService) Get(username string) (*User, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/user?username=%s", username)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-get
|
||||
func (s *UserService) GetWithContext(ctx context.Context, accountId string) (*User, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/user?accountId=%s", accountId)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -65,12 +64,41 @@ func (s *UserService) Get(username string) (*User, *Response, error) {
|
|||
return user, resp, nil
|
||||
}
|
||||
|
||||
// Create creates an user in JIRA.
|
||||
// Get wraps GetWithContext using the background context.
|
||||
func (s *UserService) Get(accountId string) (*User, *Response, error) {
|
||||
return s.GetWithContext(context.Background(), accountId)
|
||||
}
|
||||
|
||||
// GetByAccountIDWithContext gets user info from Jira
|
||||
// Searching by another parameter that is not accountId is deprecated,
|
||||
// but this method is kept for backwards compatibility
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUser
|
||||
func (s *UserService) GetByAccountIDWithContext(ctx context.Context, accountID string) (*User, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/user?accountId=%s", accountID)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
user := new(User)
|
||||
resp, err := s.client.Do(req, user)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
return user, resp, nil
|
||||
}
|
||||
|
||||
// GetByAccountID wraps GetByAccountIDWithContext using the background context.
|
||||
func (s *UserService) GetByAccountID(accountID string) (*User, *Response, error) {
|
||||
return s.GetByAccountIDWithContext(context.Background(), accountID)
|
||||
}
|
||||
|
||||
// CreateWithContext creates an user in Jira.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-createUser
|
||||
func (s *UserService) Create(user *User) (*User, *Response, error) {
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-createUser
|
||||
func (s *UserService) CreateWithContext(ctx context.Context, user *User) (*User, *Response, error) {
|
||||
apiEndpoint := "/rest/api/2/user"
|
||||
req, err := s.client.NewRequest("POST", apiEndpoint, user)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, user)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -84,24 +112,30 @@ func (s *UserService) Create(user *User) (*User, *Response, error) {
|
|||
defer resp.Body.Close()
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
e := fmt.Errorf("Could not read the returned data")
|
||||
e := fmt.Errorf("could not read the returned data")
|
||||
return nil, resp, NewJiraError(resp, e)
|
||||
}
|
||||
err = json.Unmarshal(data, responseUser)
|
||||
if err != nil {
|
||||
e := fmt.Errorf("Could not unmarshall the data into struct")
|
||||
e := fmt.Errorf("could not unmarshall the data into struct")
|
||||
return nil, resp, NewJiraError(resp, e)
|
||||
}
|
||||
return responseUser, resp, nil
|
||||
}
|
||||
|
||||
// Delete deletes an user from JIRA.
|
||||
// Create wraps CreateWithContext using the background context.
|
||||
func (s *UserService) Create(user *User) (*User, *Response, error) {
|
||||
return s.CreateWithContext(context.Background(), user)
|
||||
}
|
||||
|
||||
// DeleteWithContext deletes an user from Jira.
|
||||
// Returns http.StatusNoContent on success.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-user-delete
|
||||
func (s *UserService) Delete(username string) (*Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/user?username=%s", username)
|
||||
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil)
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-delete
|
||||
// Caller must close resp.Body
|
||||
func (s *UserService) DeleteWithContext(ctx context.Context, accountId string) (*Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/user?accountId=%s", accountId)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -113,12 +147,18 @@ func (s *UserService) Delete(username string) (*Response, error) {
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
// GetGroups returns the groups which the user belongs to
|
||||
// Delete wraps DeleteWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *UserService) Delete(accountId string) (*Response, error) {
|
||||
return s.DeleteWithContext(context.Background(), accountId)
|
||||
}
|
||||
|
||||
// GetGroupsWithContext returns the groups which the user belongs to
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUserGroups
|
||||
func (s *UserService) GetGroups(username string) (*[]UserGroup, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/user/groups?username=%s", username)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-groups-get
|
||||
func (s *UserService) GetGroupsWithContext(ctx context.Context, accountId string) (*[]UserGroup, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/user/groups?accountId=%s", accountId)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -131,12 +171,17 @@ func (s *UserService) GetGroups(username string) (*[]UserGroup, *Response, error
|
|||
return userGroups, resp, nil
|
||||
}
|
||||
|
||||
// Get information about the current logged-in user
|
||||
// GetGroups wraps GetGroupsWithContext using the background context.
|
||||
func (s *UserService) GetGroups(accountId string) (*[]UserGroup, *Response, error) {
|
||||
return s.GetGroupsWithContext(context.Background(), accountId)
|
||||
}
|
||||
|
||||
// GetSelfWithContext information about the current logged-in user
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-myself-get
|
||||
func (s *UserService) GetSelf() (*User, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-myself-get
|
||||
func (s *UserService) GetSelfWithContext(ctx context.Context) (*User, *Response, error) {
|
||||
const apiEndpoint = "rest/api/2/myself"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -148,6 +193,11 @@ func (s *UserService) GetSelf() (*User, *Response, error) {
|
|||
return &user, resp, nil
|
||||
}
|
||||
|
||||
// GetSelf wraps GetSelfWithContext using the background context.
|
||||
func (s *UserService) GetSelf() (*User, *Response, error) {
|
||||
return s.GetSelfWithContext(context.Background())
|
||||
}
|
||||
|
||||
// WithMaxResults sets the max results to return
|
||||
func WithMaxResults(maxResults int) userSearchF {
|
||||
return func(s userSearch) userSearch {
|
||||
|
@ -180,14 +230,38 @@ func WithInactive(inactive bool) userSearchF {
|
|||
}
|
||||
}
|
||||
|
||||
// Find searches for user info from JIRA:
|
||||
// It can find users by email, username or name
|
||||
// WithUsername sets the username to search
|
||||
func WithUsername(username string) userSearchF {
|
||||
return func(s userSearch) userSearch {
|
||||
s = append(s, userSearchParam{name: "username", value: username})
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// WithAccountId sets the account id to search
|
||||
func WithAccountId(accountId string) userSearchF {
|
||||
return func(s userSearch) userSearch {
|
||||
s = append(s, userSearchParam{name: "accountId", value: accountId})
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// WithProperty sets the property (Property keys are specified by path) to search
|
||||
func WithProperty(property string) userSearchF {
|
||||
return func(s userSearch) userSearch {
|
||||
s = append(s, userSearchParam{name: "property", value: property})
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// FindWithContext searches for user info from Jira:
|
||||
// It can find users by email or display name using the query parameter
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-findUsers
|
||||
func (s *UserService) Find(property string, tweaks ...userSearchF) ([]User, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-search-get
|
||||
func (s *UserService) FindWithContext(ctx context.Context, property string, tweaks ...userSearchF) ([]User, *Response, error) {
|
||||
search := []userSearchParam{
|
||||
{
|
||||
name: "username",
|
||||
name: "query",
|
||||
value: property,
|
||||
},
|
||||
}
|
||||
|
@ -201,7 +275,7 @@ func (s *UserService) Find(property string, tweaks ...userSearchF) ([]User, *Res
|
|||
}
|
||||
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/user/search?%s", queryString[:len(queryString)-1])
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -213,3 +287,8 @@ func (s *UserService) Find(property string, tweaks ...userSearchF) ([]User, *Res
|
|||
}
|
||||
return users, resp, nil
|
||||
}
|
||||
|
||||
// Find wraps FindWithContext using the background context.
|
||||
func (s *UserService) Find(property string, tweaks ...userSearchF) ([]User, *Response, error) {
|
||||
return s.FindWithContext(context.Background(), property, tweaks...)
|
||||
}
|
||||
|
|
54
vendor/github.com/andygrunwald/go-jira/version.go
generated
vendored
54
vendor/github.com/andygrunwald/go-jira/version.go
generated
vendored
|
@ -1,14 +1,15 @@
|
|||
package jira
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// VersionService handles Versions for the JIRA instance / API.
|
||||
// VersionService handles Versions for the Jira instance / API.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/version
|
||||
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/version
|
||||
type VersionService struct {
|
||||
client *Client
|
||||
}
|
||||
|
@ -19,20 +20,20 @@ type Version struct {
|
|||
ID string `json:"id,omitempty" structs:"id,omitempty"`
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
Description string `json:"description,omitempty" structs:"description,omitempty"`
|
||||
Archived bool `json:"archived,omitempty" structs:"archived,omitempty"`
|
||||
Released bool `json:"released,omitempty" structs:"released,omitempty"`
|
||||
Archived *bool `json:"archived,omitempty" structs:"archived,omitempty"`
|
||||
Released *bool `json:"released,omitempty" structs:"released,omitempty"`
|
||||
ReleaseDate string `json:"releaseDate,omitempty" structs:"releaseDate,omitempty"`
|
||||
UserReleaseDate string `json:"userReleaseDate,omitempty" structs:"userReleaseDate,omitempty"`
|
||||
ProjectID int `json:"projectId,omitempty" structs:"projectId,omitempty"` // Unlike other IDs, this is returned as a number
|
||||
StartDate string `json:"startDate,omitempty" structs:"startDate,omitempty"`
|
||||
}
|
||||
|
||||
// Get gets version info from JIRA
|
||||
// GetWithContext gets version info from Jira
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-id-get
|
||||
func (s *VersionService) Get(versionID int) (*Version, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-id-get
|
||||
func (s *VersionService) GetWithContext(ctx context.Context, versionID int) (*Version, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/version/%v", versionID)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -45,12 +46,17 @@ func (s *VersionService) Get(versionID int) (*Version, *Response, error) {
|
|||
return version, resp, nil
|
||||
}
|
||||
|
||||
// Create creates a version in JIRA.
|
||||
// Get wraps GetWithContext using the background context.
|
||||
func (s *VersionService) Get(versionID int) (*Version, *Response, error) {
|
||||
return s.GetWithContext(context.Background(), versionID)
|
||||
}
|
||||
|
||||
// CreateWithContext creates a version in Jira.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-post
|
||||
func (s *VersionService) Create(version *Version) (*Version, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-post
|
||||
func (s *VersionService) CreateWithContext(ctx context.Context, version *Version) (*Version, *Response, error) {
|
||||
apiEndpoint := "/rest/api/2/version"
|
||||
req, err := s.client.NewRequest("POST", apiEndpoint, version)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, version)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -64,23 +70,29 @@ func (s *VersionService) Create(version *Version) (*Version, *Response, error) {
|
|||
defer resp.Body.Close()
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
e := fmt.Errorf("Could not read the returned data")
|
||||
e := fmt.Errorf("could not read the returned data")
|
||||
return nil, resp, NewJiraError(resp, e)
|
||||
}
|
||||
err = json.Unmarshal(data, responseVersion)
|
||||
if err != nil {
|
||||
e := fmt.Errorf("Could not unmarshall the data into struct")
|
||||
e := fmt.Errorf("could not unmarshall the data into struct")
|
||||
return nil, resp, NewJiraError(resp, e)
|
||||
}
|
||||
return responseVersion, resp, nil
|
||||
}
|
||||
|
||||
// Update updates a version from a JSON representation.
|
||||
// Create wraps CreateWithContext using the background context.
|
||||
func (s *VersionService) Create(version *Version) (*Version, *Response, error) {
|
||||
return s.CreateWithContext(context.Background(), version)
|
||||
}
|
||||
|
||||
// UpdateWithContext updates a version from a JSON representation.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-id-put
|
||||
func (s *VersionService) Update(version *Version) (*Version, *Response, error) {
|
||||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-id-put
|
||||
// Caller must close resp.Body
|
||||
func (s *VersionService) UpdateWithContext(ctx context.Context, version *Version) (*Version, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/api/2/version/%v", version.ID)
|
||||
req, err := s.client.NewRequest("PUT", apiEndpoint, version)
|
||||
req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, version)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -95,3 +107,9 @@ func (s *VersionService) Update(version *Version) (*Version, *Response, error) {
|
|||
ret := *version
|
||||
return &ret, resp, nil
|
||||
}
|
||||
|
||||
// Update wraps UpdateWithContext using the background context.
|
||||
// Caller must close resp.Body
|
||||
func (s *VersionService) Update(version *Version) (*Version, *Response, error) {
|
||||
return s.UpdateWithContext(context.Background(), version)
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue