mirror of
https://github.com/documize/community.git
synced 2025-07-19 05:09:42 +02:00
Change RefID field size from 16 to 20 with updated algo
Xid dependency updated. Moved to 20 length ID values. Added new revision number to version and meta information. Revision number is timestamp format.
This commit is contained in:
parent
7860bc1808
commit
391c143483
25 changed files with 2123 additions and 878 deletions
|
@ -32,7 +32,7 @@ RENAME TABLE
|
|||
|
||||
-- field renaming
|
||||
ALTER TABLE dmz_org
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `company` `c_company` VARCHAR(500) NOT NULL,
|
||||
CHANGE `title` `c_title` VARCHAR(500) NOT NULL,
|
||||
CHANGE `message` `c_message` VARCHAR(500) NOT NULL,
|
||||
|
@ -50,9 +50,9 @@ ALTER TABLE dmz_org
|
|||
CHANGE `revised` `c_revised` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_space
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `type` `c_type` INT NOT NULL DEFAULT 1,
|
||||
CHANGE `lifecycle` `c_lifecycle` INT NOT NULL DEFAULT 1,
|
||||
CHANGE `label` `c_name` VARCHAR(300) NOT NULL,
|
||||
|
@ -61,52 +61,52 @@ ALTER TABLE dmz_space
|
|||
CHANGE `revised` `c_revised` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_category
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `labelid` `c_spaceid` CHAR(16) NOT NULL,
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `labelid` `c_spaceid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `category` `c_name` VARCHAR(50) NOT NULL,
|
||||
CHANGE `created` `c_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CHANGE `revised` `c_revised` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_category_member
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `labelid` `c_spaceid` CHAR(16) NOT NULL,
|
||||
CHANGE `categoryid` `c_categoryid` CHAR(16) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` CHAR(16) NOT NULL,
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `labelid` `c_spaceid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `categoryid` `c_categoryid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `created` `c_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CHANGE `revised` `c_revised` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_group
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `role` `c_name` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
CHANGE `purpose` `c_desc` VARCHAR(100) DEFAULT '',
|
||||
CHANGE `created` `c_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CHANGE `revised` `c_revised` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_group_member
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `roleid` `c_groupid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL;
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `roleid` `c_groupid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL;
|
||||
|
||||
|
||||
ALTER TABLE dmz_permission
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `who` `c_who` VARCHAR(30) NOT NULL,
|
||||
CHANGE `whoid` `c_whoid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `whoid` `c_whoid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `action` `c_action` VARCHAR(30) NOT NULL,
|
||||
CHANGE `scope` `c_scope` VARCHAR(30) NOT NULL,
|
||||
CHANGE `location` `c_location` VARCHAR(100) NOT NULL,
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `created` `c_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
|
||||
ALTER TABLE dmz_doc
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `labelid` `c_spaceid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `labelid` `c_spaceid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `job` `c_job` CHAR(36) NOT NULL DEFAULT '',
|
||||
CHANGE `location` `c_location` VARCHAR(2000) NOT NULL DEFAULT '',
|
||||
CHANGE `title` `c_name` VARCHAR(2000) NOT NULL DEFAULT '',
|
||||
|
@ -120,44 +120,44 @@ ALTER TABLE dmz_doc
|
|||
CHANGE `versioned` `c_versioned` BOOL NOT NULL DEFAULT 0,
|
||||
CHANGE `versionid` `c_versionid` VARCHAR(100) NOT NULL DEFAULT '',
|
||||
CHANGE `versionorder` `c_versionorder` INT NOT NULL DEFAULT 0,
|
||||
CHANGE `groupid` `c_groupid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `groupid` `c_groupid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `created` `c_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CHANGE `revised` `c_revised` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_doc_share
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) DEFAULT '',
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) DEFAULT '',
|
||||
CHANGE `email` `c_email` VARCHAR(250) NOT NULL DEFAULT '',
|
||||
CHANGE `message` `c_message` VARCHAR(500) NOT NULL DEFAULT '',
|
||||
CHANGE `viewed` `c_viewed` VARCHAR(500) NOT NULL DEFAULT '',
|
||||
CHANGE `secret` `c_secret` VARCHAR(250) NOT NULL DEFAULT '',
|
||||
CHANGE `expires` `c_expires` CHAR(16) DEFAULT '',
|
||||
CHANGE `expires` `c_expires` VARCHAR(20) DEFAULT '',
|
||||
CHANGE `active` `c_active` BOOL NOT NULL DEFAULT 1,
|
||||
CHANGE `created` `c_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_doc_vote
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` CHAR(16) NOT NULL,
|
||||
CHANGE `voter` `c_voter` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `voter` `c_voter` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `vote` `c_vote` INT NOT NULL DEFAULT 0,
|
||||
CHANGE `created` `c_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CHANGE `revised` `c_revised` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_doc_comment
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) DEFAULT '',
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) DEFAULT '',
|
||||
CHANGE `email` `c_email` VARCHAR(250) NOT NULL DEFAULT '',
|
||||
CHANGE `feedback` `c_feedback` LONGTEXT,
|
||||
CHANGE `created` `c_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_doc_attachment
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` CHAR(16) NOT NULL,
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `job` `c_job` CHAR(36) NOT NULL,
|
||||
CHANGE `fileid` `c_fileid` CHAR(10) NOT NULL,
|
||||
CHANGE `filename` `c_filename` VARCHAR(255) NOT NULL,
|
||||
|
@ -167,43 +167,43 @@ ALTER TABLE dmz_doc_attachment
|
|||
CHANGE `revised` `c_revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_doc_link
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `folderid` `c_spaceid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL,
|
||||
CHANGE `sourcedocumentid` `c_sourcedocid` CHAR(16) NOT NULL,
|
||||
CHANGE `sourcepageid` `c_sourcesectionid` CHAR(16) NOT NULL,
|
||||
CHANGE `linktype` `c_type` CHAR(16) NOT NULL,
|
||||
CHANGE `targetdocumentid` `c_targetdocid` CHAR(16) NOT NULL,
|
||||
CHANGE `targetid` `c_targetid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `folderid` `c_spaceid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `sourcedocumentid` `c_sourcedocid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `sourcepageid` `c_sourcesectionid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `linktype` `c_type` VARCHAR(20) NOT NULL,
|
||||
CHANGE `targetdocumentid` `c_targetdocid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `targetid` `c_targetid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `externalid` `c_externalid` VARCHAR(1000) NOT NULL DEFAULT '',
|
||||
CHANGE `orphan` `c_orphan` BOOL NOT NULL DEFAULT 0,
|
||||
CHANGE `created` `c_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CHANGE `revised` `c_revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_section
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `pagetype` `c_type` CHAR(10) NOT NULL DEFAULT 'section',
|
||||
CHANGE `contenttype` `c_contenttype` CHAR(20) NOT NULL DEFAULT 'wysiwyg',
|
||||
CHANGE `blockid` `c_templateid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `blockid` `c_templateid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `level` `c_level` INT UNSIGNED NOT NULL,
|
||||
CHANGE `sequence` `c_sequence` DOUBLE NOT NULL,
|
||||
CHANGE `title` `c_name` VARCHAR(2000) NOT NULL DEFAULT '',
|
||||
CHANGE `body` `c_body` LONGTEXT,
|
||||
CHANGE `revisions` `c_revisions` INT UNSIGNED NOT NULL,
|
||||
CHANGE `status` `c_status` INT NOT NULL DEFAULT 0,
|
||||
CHANGE `relativeid` `c_relativeid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `relativeid` `c_relativeid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `created` `c_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CHANGE `revised` `c_revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_section_meta
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `pageid` `c_sectionid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `pageid` `c_sectionid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `rawbody` `c_rawbody` LONGBLOB,
|
||||
CHANGE `config` `c_config` JSON,
|
||||
CHANGE `externalsource` `c_external` BOOL DEFAULT 0,
|
||||
|
@ -211,10 +211,10 @@ ALTER TABLE dmz_section_meta
|
|||
CHANGE `revised` `c_revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_section_template
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `labelid` `c_spaceid` CHAR(16) DEFAULT '',
|
||||
CHANGE `userid` `c_userid` CHAR(16) DEFAULT '',
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `labelid` `c_spaceid` VARCHAR(20) DEFAULT '',
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) DEFAULT '',
|
||||
CHANGE `pagetype` `c_type` CHAR(10) NOT NULL DEFAULT 'section',
|
||||
CHANGE `contenttype` `c_contenttype` CHAR(20) NOT NULL DEFAULT 'wysiwyg',
|
||||
CHANGE `title` `c_name` VARCHAR(2000) NOT NULL DEFAULT '',
|
||||
|
@ -228,12 +228,12 @@ ALTER TABLE dmz_section_template
|
|||
CHANGE `revised` `c_revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_section_revision
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` CHAR(16) NOT NULL,
|
||||
CHANGE `ownerid` `c_ownerid` CHAR(16) DEFAULT '',
|
||||
CHANGE `pageid` `c_sectionid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL,
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `ownerid` `c_ownerid` VARCHAR(20) DEFAULT '',
|
||||
CHANGE `pageid` `c_sectionid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `pagetype` `c_type` CHAR(10) NOT NULL DEFAULT 'section',
|
||||
CHANGE `contenttype` `c_contenttype` CHAR(20) NOT NULL DEFAULT 'wysiwyg',
|
||||
CHANGE `title` `c_name` VARCHAR(2000) NOT NULL DEFAULT '',
|
||||
|
@ -244,7 +244,7 @@ ALTER TABLE dmz_section_revision
|
|||
CHANGE `revised` `c_revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_user
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `firstname` `c_firstname` VARCHAR(500) NOT NULL DEFAULT '',
|
||||
CHANGE `lastname` `c_lastname` VARCHAR(500) NOT NULL DEFAULT '',
|
||||
CHANGE `email` `c_email` VARCHAR(500) NOT NULL DEFAULT '',
|
||||
|
@ -254,14 +254,14 @@ ALTER TABLE dmz_user
|
|||
CHANGE `salt` `c_salt` VARCHAR(500) NOT NULL DEFAULT '',
|
||||
CHANGE `reset` `c_reset` VARCHAR(500) NOT NULL DEFAULT '',
|
||||
CHANGE `active` `c_active` BOOL NOT NULL DEFAULT 1,
|
||||
CHANGE `lastversion` `c_lastversion` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `lastversion` `c_lastversion` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `created` `c_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CHANGE `revised` `c_revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_user_account
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL,
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `editor` `c_editor` BOOL NOT NULL DEFAULT 0,
|
||||
CHANGE `admin` `c_admin` BOOL NOT NULL DEFAULT 0,
|
||||
CHANGE `users` `c_users` BOOL NOT NULL DEFAULT 1,
|
||||
|
@ -271,19 +271,19 @@ ALTER TABLE dmz_user_account
|
|||
CHANGE `revised` `c_revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_user_activity
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL,
|
||||
CHANGE `labelid` `c_spaceid` CHAR(16) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `pageid` `c_sectionid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `labelid` `c_spaceid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `pageid` `c_sectionid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `sourcetype` `c_sourcetype` INT NOT NULL DEFAULT 0,
|
||||
CHANGE `activitytype` `c_activitytype` INT NOT NULL DEFAULT 0,
|
||||
CHANGE `metadata` `c_metadata` VARCHAR(1000) NOT NULL DEFAULT '',
|
||||
CHANGE `created` `c_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_user_config
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `key` `c_key` CHAR(200) NOT NULL,
|
||||
CHANGE `config` `c_config` JSON;
|
||||
|
||||
|
@ -292,37 +292,37 @@ ALTER TABLE dmz_config
|
|||
CHANGE `config` `c_config` JSON;
|
||||
|
||||
ALTER TABLE dmz_pin
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) DEFAULT '',
|
||||
CHANGE `labelid` `c_spaceid` CHAR(16) DEFAULT '',
|
||||
CHANGE `documentid` `c_docid` CHAR(16) DEFAULT '',
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) DEFAULT '',
|
||||
CHANGE `labelid` `c_spaceid` VARCHAR(20) DEFAULT '',
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) DEFAULT '',
|
||||
CHANGE `sequence` `c_sequence` INT UNSIGNED NOT NULL DEFAULT 99,
|
||||
CHANGE `pin` `c_name` CHAR(100) NOT NULL DEFAULT '',
|
||||
CHANGE `created` `c_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CHANGE `revised` `c_revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_search
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` CHAR(16) NOT NULL,
|
||||
CHANGE `itemid` `c_itemid` CHAR(16) NOT NULL DEFAULT '',
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `itemid` `c_itemid` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
CHANGE `itemtype` `c_itemtype` VARCHAR(10) NOT NULL,
|
||||
CHANGE `content` `c_content` LONGTEXT,
|
||||
CHANGE `created` `c_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_audit_log
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `eventtype` `c_eventtype` VARCHAR(100) NOT NULL DEFAULT '',
|
||||
CHANGE `ip` `c_ip` VARCHAR(39) NOT NULL DEFAULT '',
|
||||
CHANGE `created` `c_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE dmz_action
|
||||
CHANGE `refid` `c_refid` CHAR(16) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` CHAR(16) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` CHAR(16) NOT NULL,
|
||||
CHANGE `userid` `c_userid` CHAR(16) NOT NULL,
|
||||
CHANGE `requestorid` `c_requestorid` CHAR(16) NOT NULL,
|
||||
CHANGE `refid` `c_refid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `orgid` `c_orgid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `documentid` `c_docid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `userid` `c_userid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `requestorid` `c_requestorid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `actiontype` `c_actiontype` INT NOT NULL DEFAULT 0,
|
||||
CHANGE `note` `c_note` VARCHAR(2000) NOT NULL DEFAULT '',
|
||||
CHANGE `requested` `c_requested` TIMESTAMP NULL,
|
||||
|
@ -330,7 +330,7 @@ ALTER TABLE dmz_action
|
|||
CHANGE `completed` `c_completed` TIMESTAMP NULL,
|
||||
CHANGE `iscomplete` `c_iscomplete` BOOL NOT NULL DEFAULT 0,
|
||||
CHANGE `reftype` `c_reftype` CHAR(1) NOT NULL DEFAULT 'D',
|
||||
CHANGE `reftypeid` `c_reftypeid` CHAR(16) NOT NULL,
|
||||
CHANGE `reftypeid` `c_reftypeid` VARCHAR(20) NOT NULL,
|
||||
CHANGE `created` `c_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CHANGE `revised` `c_revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
DROP TABLE IF EXISTS dmz_action;
|
||||
CREATE TABLE dmz_action (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_requestorid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_requestorid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_actiontype int NOT NULL DEFAULT '0',
|
||||
c_note varchar(2000) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_requested timestamp NULL DEFAULT NULL,
|
||||
|
@ -18,7 +18,7 @@ CREATE TABLE dmz_action (
|
|||
c_completed timestamp NULL DEFAULT NULL,
|
||||
c_iscomplete bool NOT NULL DEFAULT '0',
|
||||
c_reftype varchar(1) COLLATE ucs_basic NOT NULL DEFAULT 'D',
|
||||
c_reftypeid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_reftypeid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
c_revised timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id)
|
||||
|
@ -31,8 +31,8 @@ CREATE INDEX idx_action_4 ON dmz_action (c_requestorid);
|
|||
DROP TABLE IF EXISTS dmz_audit_log;
|
||||
CREATE TABLE dmz_audit_log (
|
||||
id bigserial NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_eventtype varchar(100) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_ip varchar(39) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
@ -45,9 +45,9 @@ CREATE INDEX idx_audit_log_3 ON dmz_audit_log (c_eventtype);
|
|||
DROP TABLE IF EXISTS dmz_category;
|
||||
CREATE TABLE dmz_category (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_name varchar(50) COLLATE ucs_basic NOT NULL,
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
c_revised timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
@ -60,11 +60,11 @@ CREATE INDEX idx_category_3 ON dmz_category (c_orgid,c_spaceid);
|
|||
DROP TABLE IF EXISTS dmz_category_member;
|
||||
CREATE TABLE dmz_category_member (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_categoryid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_categoryid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
c_revised timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE (id)
|
||||
|
@ -83,10 +83,10 @@ CREATE TABLE dmz_config (
|
|||
DROP TABLE IF EXISTS dmz_doc;
|
||||
CREATE TABLE dmz_doc (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_job varchar(36) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_location varchar(2000) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_name varchar(2000) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
|
@ -100,7 +100,7 @@ CREATE TABLE dmz_doc (
|
|||
c_versioned bool NOT NULL DEFAULT '0',
|
||||
c_versionid varchar(100) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_versionorder int NOT NULL DEFAULT '0',
|
||||
c_groupid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_groupid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
c_revised timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (c_refid)
|
||||
|
@ -112,9 +112,9 @@ CREATE INDEX idx_doc_3 ON dmz_doc (c_spaceid);
|
|||
DROP TABLE IF EXISTS dmz_doc_attachment;
|
||||
CREATE TABLE dmz_doc_attachment (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_job varchar(36) COLLATE ucs_basic NOT NULL,
|
||||
c_fileid varchar(10) COLLATE ucs_basic NOT NULL,
|
||||
c_filename varchar(255) COLLATE ucs_basic NOT NULL,
|
||||
|
@ -132,10 +132,10 @@ CREATE INDEX idx_doc_attachment_4 ON dmz_doc_attachment (c_job,c_fileid);
|
|||
DROP TABLE IF EXISTS dmz_doc_comment;
|
||||
CREATE TABLE dmz_doc_comment (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic DEFAULT '',
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic DEFAULT '',
|
||||
c_email varchar(250) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_feedback text COLLATE ucs_basic,
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
@ -146,15 +146,15 @@ CREATE INDEX idx_doc_comment_1 ON dmz_doc_comment (c_refid);
|
|||
DROP TABLE IF EXISTS dmz_doc_link;
|
||||
CREATE TABLE dmz_doc_link (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_sourcedocid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_sourcesectionid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_type varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_targetdocid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_targetid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_sourcedocid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_sourcesectionid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_type varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_targetdocid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_targetid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_externalid varchar(1000) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_orphan bool NOT NULL DEFAULT '0',
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
@ -165,14 +165,14 @@ CREATE TABLE dmz_doc_link (
|
|||
DROP TABLE IF EXISTS dmz_doc_share;
|
||||
CREATE TABLE dmz_doc_share (
|
||||
id bigserial NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic DEFAULT '',
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic DEFAULT '',
|
||||
c_email varchar(250) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_message varchar(500) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_viewed varchar(500) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_secret varchar(250) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_expires varchar(16) COLLATE ucs_basic DEFAULT '',
|
||||
c_expires varchar(20) COLLATE ucs_basic DEFAULT '',
|
||||
c_active bool NOT NULL DEFAULT '1',
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id)
|
||||
|
@ -181,10 +181,10 @@ CREATE TABLE dmz_doc_share (
|
|||
DROP TABLE IF EXISTS dmz_doc_vote;
|
||||
CREATE TABLE dmz_doc_vote (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_voter varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_voter varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_vote int NOT NULL DEFAULT '0',
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
c_revised timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
@ -198,8 +198,8 @@ CREATE INDEX idx_doc_vote_4 ON dmz_doc_vote (c_orgid,c_docid);
|
|||
DROP TABLE IF EXISTS dmz_group;
|
||||
CREATE TABLE dmz_group (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_name varchar(50) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_desc varchar(100) COLLATE ucs_basic DEFAULT '',
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
@ -212,9 +212,9 @@ CREATE INDEX idx_group_2 ON dmz_group (c_orgid);
|
|||
DROP TABLE IF EXISTS dmz_group_member;
|
||||
CREATE TABLE dmz_group_member (
|
||||
id bigserial NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_groupid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_groupid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
UNIQUE (id)
|
||||
);
|
||||
CREATE INDEX idx_group_member_1 ON dmz_group_member (c_groupid,c_userid);
|
||||
|
@ -223,7 +223,7 @@ CREATE INDEX idx_group_member_2 ON dmz_group_member (c_orgid,c_groupid,c_userid)
|
|||
DROP TABLE IF EXISTS dmz_org;
|
||||
CREATE TABLE dmz_org (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_company varchar(500) COLLATE ucs_basic NOT NULL,
|
||||
c_title varchar(500) COLLATE ucs_basic NOT NULL,
|
||||
c_message varchar(500) COLLATE ucs_basic NOT NULL,
|
||||
|
@ -247,13 +247,13 @@ CREATE INDEX idx_org_2 ON dmz_org (c_domain);
|
|||
DROP TABLE IF EXISTS dmz_permission;
|
||||
CREATE TABLE dmz_permission (
|
||||
id bigserial NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_who varchar(30) COLLATE ucs_basic NOT NULL,
|
||||
c_whoid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_whoid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_action varchar(30) COLLATE ucs_basic NOT NULL,
|
||||
c_scope varchar(30) COLLATE ucs_basic NOT NULL,
|
||||
c_location varchar(100) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE (id)
|
||||
);
|
||||
|
@ -266,11 +266,11 @@ CREATE INDEX idx_permission_5 ON dmz_permission (c_orgid,c_who,c_location,c_acti
|
|||
DROP TABLE IF EXISTS dmz_pin;
|
||||
CREATE TABLE dmz_pin (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic DEFAULT '',
|
||||
c_spaceid varchar(16) COLLATE ucs_basic DEFAULT '',
|
||||
c_docid varchar(16) COLLATE ucs_basic DEFAULT '',
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic DEFAULT '',
|
||||
c_spaceid varchar(20) COLLATE ucs_basic DEFAULT '',
|
||||
c_docid varchar(20) COLLATE ucs_basic DEFAULT '',
|
||||
c_sequence BIGINT NOT NULL DEFAULT '99',
|
||||
c_name varchar(100) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
@ -282,9 +282,9 @@ CREATE INDEX idx_pin_1 ON dmz_pin (c_userid);
|
|||
DROP TABLE IF EXISTS dmz_search;
|
||||
CREATE TABLE dmz_search (
|
||||
id bigserial NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_itemid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_itemid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_itemtype varchar(10) COLLATE ucs_basic NOT NULL,
|
||||
c_content text COLLATE ucs_basic,
|
||||
c_token TSVECTOR,
|
||||
|
@ -298,20 +298,20 @@ CREATE INDEX idx_search_3 ON dmz_search USING GIN(c_token);
|
|||
DROP TABLE IF EXISTS dmz_section;
|
||||
CREATE TABLE dmz_section (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_contenttype varchar(20) COLLATE ucs_basic NOT NULL DEFAULT 'wysiwyg',
|
||||
c_type varchar(10) COLLATE ucs_basic NOT NULL DEFAULT 'section',
|
||||
c_templateid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_templateid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_level bigint NOT NULL,
|
||||
c_sequence double precision NOT NULL,
|
||||
c_name varchar(2000) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_body text COLLATE ucs_basic,
|
||||
c_revisions bigint NOT NULL,
|
||||
c_status int NOT NULL DEFAULT '0',
|
||||
c_relativeid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_relativeid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
c_revised timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (c_refid)
|
||||
|
@ -323,10 +323,10 @@ CREATE INDEX idx_section_3 ON dmz_section (c_docid);
|
|||
DROP TABLE IF EXISTS dmz_section_meta;
|
||||
CREATE TABLE dmz_section_meta (
|
||||
id bigserial NOT NULL,
|
||||
c_sectionid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_docid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_sectionid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_docid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_rawbody BYTEA,
|
||||
c_config json DEFAULT NULL,
|
||||
c_external bool DEFAULT '0',
|
||||
|
@ -342,12 +342,12 @@ CREATE INDEX idx_section_meta_4 ON dmz_section_meta (c_docid);
|
|||
DROP TABLE IF EXISTS dmz_section_revision;
|
||||
CREATE TABLE dmz_section_revision (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_ownerid varchar(16) COLLATE ucs_basic DEFAULT '',
|
||||
c_sectionid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_ownerid varchar(20) COLLATE ucs_basic DEFAULT '',
|
||||
c_sectionid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_contenttype varchar(20) COLLATE ucs_basic NOT NULL DEFAULT 'wysiwyg',
|
||||
c_type varchar(10) COLLATE ucs_basic NOT NULL DEFAULT 'section',
|
||||
c_name varchar(2000) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
|
@ -366,10 +366,10 @@ CREATE INDEX idx_section_revision_4 ON dmz_section_revision (c_sectionid);
|
|||
DROP TABLE IF EXISTS dmz_section_template;
|
||||
CREATE TABLE dmz_section_template (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(16) COLLATE ucs_basic DEFAULT '',
|
||||
c_userid varchar(16) COLLATE ucs_basic DEFAULT '',
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(20) COLLATE ucs_basic DEFAULT '',
|
||||
c_userid varchar(20) COLLATE ucs_basic DEFAULT '',
|
||||
c_contenttype varchar(20) COLLATE ucs_basic NOT NULL DEFAULT 'wysiwyg',
|
||||
c_type varchar(10) COLLATE ucs_basic NOT NULL DEFAULT 'section',
|
||||
c_name varchar(2000) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
|
@ -389,10 +389,10 @@ CREATE INDEX idx_section_template_2 ON dmz_section_template (c_spaceid);
|
|||
DROP TABLE IF EXISTS dmz_space;
|
||||
CREATE TABLE dmz_space (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_name varchar(300) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_type int NOT NULL DEFAULT '1',
|
||||
c_lifecycle int NOT NULL DEFAULT '1',
|
||||
c_likes varchar(1000) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
|
@ -407,7 +407,7 @@ CREATE INDEX idx_space_3 ON dmz_space (c_orgid);
|
|||
DROP TABLE IF EXISTS dmz_user;
|
||||
CREATE TABLE dmz_user (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_firstname varchar(500) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_lastname varchar(500) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_email varchar(500) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
|
@ -417,7 +417,7 @@ CREATE TABLE dmz_user (
|
|||
c_salt varchar(500) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_reset varchar(500) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_active bool NOT NULL DEFAULT '1',
|
||||
c_lastversion varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_lastversion varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
c_revised timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (c_refid)
|
||||
|
@ -428,9 +428,9 @@ CREATE INDEX idx_user_2 ON dmz_user (c_email);
|
|||
DROP TABLE IF EXISTS dmz_user_account;
|
||||
CREATE TABLE dmz_user_account (
|
||||
id bigserial NOT NULL,
|
||||
c_refid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_refid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_editor bool NOT NULL DEFAULT '0',
|
||||
c_admin bool NOT NULL DEFAULT '0',
|
||||
c_users bool NOT NULL DEFAULT '1',
|
||||
|
@ -447,11 +447,11 @@ CREATE INDEX idx_user_account_3 ON dmz_user_account (c_orgid);
|
|||
DROP TABLE IF EXISTS dmz_user_activity;
|
||||
CREATE TABLE dmz_user_activity (
|
||||
id bigserial NOT NULL,
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_sectionid varchar(16) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_spaceid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_docid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_sectionid varchar(20) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
c_sourcetype int NOT NULL DEFAULT '0',
|
||||
c_activitytype int NOT NULL DEFAULT '0',
|
||||
c_metadata varchar(1000) COLLATE ucs_basic NOT NULL DEFAULT '',
|
||||
|
@ -466,8 +466,8 @@ CREATE INDEX idx_user_activity_5 ON dmz_user_activity (c_orgid,c_docid,c_userid,
|
|||
|
||||
DROP TABLE IF EXISTS dmz_user_config;
|
||||
CREATE TABLE dmz_user_config (
|
||||
c_orgid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(16) COLLATE ucs_basic NOT NULL,
|
||||
c_orgid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_userid varchar(20) COLLATE ucs_basic NOT NULL,
|
||||
c_key varchar(200) COLLATE ucs_basic NOT NULL,
|
||||
c_config json DEFAULT NULL,
|
||||
UNIQUE (c_orgid,c_userid,c_key)
|
||||
|
|
1
core/env/product.go
vendored
1
core/env/product.go
vendored
|
@ -24,6 +24,7 @@ type ProdInfo struct {
|
|||
Major string
|
||||
Minor string
|
||||
Patch string
|
||||
Revision int
|
||||
License License
|
||||
}
|
||||
|
||||
|
|
|
@ -9,13 +9,29 @@
|
|||
//
|
||||
// https://documize.com
|
||||
|
||||
// Package uniqueid provides utility functions specific to the http-end-point component of Documize.
|
||||
// Package uniqueid provides randomly generated string 16 characters long.
|
||||
package uniqueid
|
||||
|
||||
import "github.com/documize/community/core/uniqueid/xid"
|
||||
import (
|
||||
"github.com/documize/community/core/uniqueid/xid"
|
||||
"github.com/documize/community/core/uniqueid/xid16"
|
||||
)
|
||||
|
||||
// Generate creates a randomly generated string suitable for use as part of an URI.
|
||||
// It returns a string that is always 16 characters long.
|
||||
func Generate() string {
|
||||
return xid.New().String()
|
||||
}
|
||||
|
||||
// Generate16 creates a randomly generated 16 character length string suitable for use as part of an URI.
|
||||
// It returns a string that is always 16 characters long.
|
||||
func Generate16() string {
|
||||
return xid16.New().String()
|
||||
}
|
||||
|
||||
// beqassjmvbajrivsc0eg
|
||||
// beqat1bmvbajrivsc0f0
|
||||
|
||||
// beqat1bmvbajrivsc1ag
|
||||
// beqat1bmvbajrivsc1g0
|
||||
// beqat1bmvbajrivsc1ug
|
||||
|
|
|
@ -23,7 +23,7 @@ var m = make(map[string]struct{})
|
|||
var mx sync.Mutex
|
||||
|
||||
func mm(t *testing.T, id string) {
|
||||
if len(id) != 16 {
|
||||
if len(id) != 20 {
|
||||
t.Errorf("len(id)=%d", len(id))
|
||||
}
|
||||
mx.Lock()
|
||||
|
|
19
core/uniqueid/xid/LICENSE
Executable file
19
core/uniqueid/xid/LICENSE
Executable file
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2015 Olivier Poitrey <rs@dailymotion.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
112
core/uniqueid/xid/README.md
Executable file
112
core/uniqueid/xid/README.md
Executable file
|
@ -0,0 +1,112 @@
|
|||
# Globally Unique ID Generator
|
||||
|
||||
REPO: https://github.com/rs/xid
|
||||
|
||||
Package xid is a globally unique id generator library, ready to be used safely directly in your server code.
|
||||
|
||||
Xid is using Mongo Object ID algorithm to generate globally unique ids with a different serialization (base64) to make it shorter when transported as a string:
|
||||
https://docs.mongodb.org/manual/reference/object-id/
|
||||
|
||||
- 4-byte value representing the seconds since the Unix epoch,
|
||||
- 3-byte machine identifier,
|
||||
- 2-byte process id, and
|
||||
- 3-byte counter, starting with a random value.
|
||||
|
||||
The binary representation of the id is compatible with Mongo 12 bytes Object IDs.
|
||||
The string representation is using base32 hex (w/o padding) for better space efficiency
|
||||
when stored in that form (20 bytes). The hex variant of base32 is used to retain the
|
||||
sortable property of the id.
|
||||
|
||||
Xid doesn't use base64 because case sensitivity and the 2 non alphanum chars may be an
|
||||
issue when transported as a string between various systems. Base36 wasn't retained either
|
||||
because 1/ it's not standard 2/ the resulting size is not predictable (not bit aligned)
|
||||
and 3/ it would not remain sortable. To validate a base32 `xid`, expect a 20 chars long,
|
||||
all lowercase sequence of `a` to `v` letters and `0` to `9` numbers (`[0-9a-v]{20}`).
|
||||
|
||||
UUIDs are 16 bytes (128 bits) and 36 chars as string representation. Twitter Snowflake
|
||||
ids are 8 bytes (64 bits) but require machine/data-center configuration and/or central
|
||||
generator servers. xid stands in between with 12 bytes (96 bits) and a more compact
|
||||
URL-safe string representation (20 chars). No configuration or central generator server
|
||||
is required so it can be used directly in server's code.
|
||||
|
||||
| Name | Binary Size | String Size | Features
|
||||
|-------------|-------------|----------------|----------------
|
||||
| [UUID] | 16 bytes | 36 chars | configuration free, not sortable
|
||||
| [shortuuid] | 16 bytes | 22 chars | configuration free, not sortable
|
||||
| [Snowflake] | 8 bytes | up to 20 chars | needs machin/DC configuration, needs central server, sortable
|
||||
| [MongoID] | 12 bytes | 24 chars | configuration free, sortable
|
||||
| xid | 12 bytes | 20 chars | configuration free, sortable
|
||||
|
||||
[UUID]: https://en.wikipedia.org/wiki/Universally_unique_identifier
|
||||
[shortuuid]: https://github.com/stochastic-technologies/shortuuid
|
||||
[Snowflake]: https://blog.twitter.com/2010/announcing-snowflake
|
||||
[MongoID]: https://docs.mongodb.org/manual/reference/object-id/
|
||||
|
||||
Features:
|
||||
|
||||
- Size: 12 bytes (96 bits), smaller than UUID, larger than snowflake
|
||||
- Base32 hex encoded by default (20 chars when transported as printable string, still sortable)
|
||||
- Non configured, you don't need set a unique machine and/or data center id
|
||||
- K-ordered
|
||||
- Embedded time with 1 second precision
|
||||
- Unicity guaranteed for 16,777,216 (24 bits) unique ids per second and per host/process
|
||||
- Lock-free (i.e.: unlike UUIDv1 and v2)
|
||||
|
||||
Best used with [zerolog](https://github.com/rs/zerolog)'s
|
||||
[RequestIDHandler](https://godoc.org/github.com/rs/zerolog/hlog#RequestIDHandler).
|
||||
|
||||
Notes:
|
||||
|
||||
- Xid is dependent on the system time, a monotonic counter and so is not cryptographically secure. If unpredictability of IDs is important, you should not use Xids. It is worth noting that most of the other UUID like implementations are also not cryptographically secure. You shoud use libraries that rely on cryptographically secure sources (like /dev/urandom on unix, crypto/rand in golang), if you want a truly random ID generator.
|
||||
|
||||
References:
|
||||
|
||||
- http://www.slideshare.net/davegardnerisme/unique-id-generation-in-distributed-systems
|
||||
- https://en.wikipedia.org/wiki/Universally_unique_identifier
|
||||
- https://blog.twitter.com/2010/announcing-snowflake
|
||||
- Python port by [Graham Abbott](https://github.com/graham): https://github.com/graham/python_xid
|
||||
- Scala port by [Egor Kolotaev](https://github.com/kolotaev): https://github.com/kolotaev/ride
|
||||
|
||||
## Install
|
||||
|
||||
go get github.com/rs/xid
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
guid := xid.New()
|
||||
|
||||
println(guid.String())
|
||||
// Output: 9m4e2mr0ui3e8a215n4g
|
||||
```
|
||||
|
||||
Get `xid` embedded info:
|
||||
|
||||
```go
|
||||
guid.Machine()
|
||||
guid.Pid()
|
||||
guid.Time()
|
||||
guid.Counter()
|
||||
```
|
||||
|
||||
## Benchmark
|
||||
|
||||
Benchmark against Go [Maxim Bublis](https://github.com/satori)'s [UUID](https://github.com/satori/go.uuid).
|
||||
|
||||
```
|
||||
BenchmarkXID 20000000 91.1 ns/op 32 B/op 1 allocs/op
|
||||
BenchmarkXID-2 20000000 55.9 ns/op 32 B/op 1 allocs/op
|
||||
BenchmarkXID-4 50000000 32.3 ns/op 32 B/op 1 allocs/op
|
||||
BenchmarkUUIDv1 10000000 204 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkUUIDv1-2 10000000 160 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkUUIDv1-4 10000000 195 ns/op 48 B/op 1 allocs/op
|
||||
BenchmarkUUIDv4 1000000 1503 ns/op 64 B/op 2 allocs/op
|
||||
BenchmarkUUIDv4-2 1000000 1427 ns/op 64 B/op 2 allocs/op
|
||||
BenchmarkUUIDv4-4 1000000 1452 ns/op 64 B/op 2 allocs/op
|
||||
```
|
||||
|
||||
Note: UUIDv1 requires a global lock, hence the performence degrading as we add more CPUs.
|
||||
|
||||
## Licenses
|
||||
|
||||
All source code is licensed under the [MIT License](https://raw.github.com/rs/xid/master/LICENSE).
|
9
core/uniqueid/xid/hostid_darwin.go
Executable file
9
core/uniqueid/xid/hostid_darwin.go
Executable file
|
@ -0,0 +1,9 @@
|
|||
// +build darwin
|
||||
|
||||
package xid
|
||||
|
||||
import "syscall"
|
||||
|
||||
func readPlatformMachineID() (string, error) {
|
||||
return syscall.Sysctl("kern.uuid")
|
||||
}
|
9
core/uniqueid/xid/hostid_fallback.go
Executable file
9
core/uniqueid/xid/hostid_fallback.go
Executable file
|
@ -0,0 +1,9 @@
|
|||
// +build !darwin,!linux,!freebsd,!windows
|
||||
|
||||
package xid
|
||||
|
||||
import "errors"
|
||||
|
||||
func readPlatformMachineID() (string, error) {
|
||||
return "", errors.New("not implemented")
|
||||
}
|
9
core/uniqueid/xid/hostid_freebsd.go
Executable file
9
core/uniqueid/xid/hostid_freebsd.go
Executable file
|
@ -0,0 +1,9 @@
|
|||
// +build freebsd
|
||||
|
||||
package xid
|
||||
|
||||
import "syscall"
|
||||
|
||||
func readPlatformMachineID() (string, error) {
|
||||
return syscall.Sysctl("kern.hostuuid")
|
||||
}
|
10
core/uniqueid/xid/hostid_linux.go
Executable file
10
core/uniqueid/xid/hostid_linux.go
Executable file
|
@ -0,0 +1,10 @@
|
|||
// +build linux
|
||||
|
||||
package xid
|
||||
|
||||
import "io/ioutil"
|
||||
|
||||
func readPlatformMachineID() (string, error) {
|
||||
b, err := ioutil.ReadFile("/sys/class/dmi/id/product_uuid")
|
||||
return string(b), err
|
||||
}
|
38
core/uniqueid/xid/hostid_windows.go
Executable file
38
core/uniqueid/xid/hostid_windows.go
Executable file
|
@ -0,0 +1,38 @@
|
|||
// +build windows
|
||||
|
||||
package xid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func readPlatformMachineID() (string, error) {
|
||||
// source: https://github.com/shirou/gopsutil/blob/master/host/host_syscall.go
|
||||
var h syscall.Handle
|
||||
err := syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, syscall.StringToUTF16Ptr(`SOFTWARE\Microsoft\Cryptography`), 0, syscall.KEY_READ|syscall.KEY_WOW64_64KEY, &h)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer syscall.RegCloseKey(h)
|
||||
|
||||
const syscallRegBufLen = 74 // len(`{`) + len(`abcdefgh-1234-456789012-123345456671` * 2) + len(`}`) // 2 == bytes/UTF16
|
||||
const uuidLen = 36
|
||||
|
||||
var regBuf [syscallRegBufLen]uint16
|
||||
bufLen := uint32(syscallRegBufLen)
|
||||
var valType uint32
|
||||
err = syscall.RegQueryValueEx(h, syscall.StringToUTF16Ptr(`MachineGuid`), nil, &valType, (*byte)(unsafe.Pointer(®Buf[0])), &bufLen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
hostID := syscall.UTF16ToString(regBuf[:])
|
||||
hostIDLen := len(hostID)
|
||||
if hostIDLen != uuidLen {
|
||||
return "", fmt.Errorf("HostID incorrect: %q\n", hostID)
|
||||
}
|
||||
|
||||
return hostID, nil
|
||||
}
|
365
core/uniqueid/xid/id.go
Executable file
365
core/uniqueid/xid/id.go
Executable file
|
@ -0,0 +1,365 @@
|
|||
// Package xid is a globally unique id generator suited for web scale
|
||||
//
|
||||
// Xid is using Mongo Object ID algorithm to generate globally unique ids:
|
||||
// https://docs.mongodb.org/manual/reference/object-id/
|
||||
//
|
||||
// - 4-byte value representing the seconds since the Unix epoch,
|
||||
// - 3-byte machine identifier,
|
||||
// - 2-byte process id, and
|
||||
// - 3-byte counter, starting with a random value.
|
||||
//
|
||||
// The binary representation of the id is compatible with Mongo 12 bytes Object IDs.
|
||||
// The string representation is using base32 hex (w/o padding) for better space efficiency
|
||||
// when stored in that form (20 bytes). The hex variant of base32 is used to retain the
|
||||
// sortable property of the id.
|
||||
//
|
||||
// Xid doesn't use base64 because case sensitivity and the 2 non alphanum chars may be an
|
||||
// issue when transported as a string between various systems. Base36 wasn't retained either
|
||||
// because 1/ it's not standard 2/ the resulting size is not predictable (not bit aligned)
|
||||
// and 3/ it would not remain sortable. To validate a base32 `xid`, expect a 20 chars long,
|
||||
// all lowercase sequence of `a` to `v` letters and `0` to `9` numbers (`[0-9a-v]{20}`).
|
||||
//
|
||||
// UUID is 16 bytes (128 bits), snowflake is 8 bytes (64 bits), xid stands in between
|
||||
// with 12 bytes with a more compact string representation ready for the web and no
|
||||
// required configuration or central generation server.
|
||||
//
|
||||
// Features:
|
||||
//
|
||||
// - Size: 12 bytes (96 bits), smaller than UUID, larger than snowflake
|
||||
// - Base32 hex encoded by default (16 bytes storage when transported as printable string)
|
||||
// - Non configured, you don't need set a unique machine and/or data center id
|
||||
// - K-ordered
|
||||
// - Embedded time with 1 second precision
|
||||
// - Unicity guaranteed for 16,777,216 (24 bits) unique ids per second and per host/process
|
||||
//
|
||||
// Best used with xlog's RequestIDHandler (https://godoc.org/github.com/rs/xlog#RequestIDHandler).
|
||||
//
|
||||
// References:
|
||||
//
|
||||
// - http://www.slideshare.net/davegardnerisme/unique-id-generation-in-distributed-systems
|
||||
// - https://en.wikipedia.org/wiki/Universally_unique_identifier
|
||||
// - https://blog.twitter.com/2010/announcing-snowflake
|
||||
package xid
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"database/sql/driver"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sort"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Code inspired from mgo/bson ObjectId
|
||||
|
||||
// ID represents a unique request id
|
||||
type ID [rawLen]byte
|
||||
|
||||
const (
|
||||
encodedLen = 20 // string encoded len
|
||||
rawLen = 12 // binary raw len
|
||||
|
||||
// encoding stores a custom version of the base32 encoding with lower case
|
||||
// letters.
|
||||
encoding = "0123456789abcdefghijklmnopqrstuv"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidID is returned when trying to unmarshal an invalid ID
|
||||
ErrInvalidID = errors.New("xid: invalid ID")
|
||||
|
||||
// objectIDCounter is atomically incremented when generating a new ObjectId
|
||||
// using NewObjectId() function. It's used as a counter part of an id.
|
||||
// This id is initialized with a random value.
|
||||
objectIDCounter = randInt()
|
||||
|
||||
// machineId stores machine id generated once and used in subsequent calls
|
||||
// to NewObjectId function.
|
||||
machineID = readMachineID()
|
||||
|
||||
// pid stores the current process id
|
||||
pid = os.Getpid()
|
||||
|
||||
nilID ID
|
||||
|
||||
// dec is the decoding map for base32 encoding
|
||||
dec [256]byte
|
||||
)
|
||||
|
||||
func init() {
|
||||
for i := 0; i < len(dec); i++ {
|
||||
dec[i] = 0xFF
|
||||
}
|
||||
for i := 0; i < len(encoding); i++ {
|
||||
dec[encoding[i]] = byte(i)
|
||||
}
|
||||
|
||||
// If /proc/self/cpuset exists and is not /, we can assume that we are in a
|
||||
// form of container and use the content of cpuset xor-ed with the PID in
|
||||
// order get a reasonable machine global unique PID.
|
||||
b, err := ioutil.ReadFile("/proc/self/cpuset")
|
||||
if err == nil && len(b) > 1 {
|
||||
pid ^= int(crc32.ChecksumIEEE(b))
|
||||
}
|
||||
}
|
||||
|
||||
// readMachineId generates machine id and puts it into the machineId global
|
||||
// variable. If this function fails to get the hostname, it will cause
|
||||
// a runtime error.
|
||||
func readMachineID() []byte {
|
||||
id := make([]byte, 3)
|
||||
hid, err := readPlatformMachineID()
|
||||
if err != nil || len(hid) == 0 {
|
||||
hid, err = os.Hostname()
|
||||
}
|
||||
if err == nil && len(hid) != 0 {
|
||||
hw := md5.New()
|
||||
hw.Write([]byte(hid))
|
||||
copy(id, hw.Sum(nil))
|
||||
} else {
|
||||
// Fallback to rand number if machine id can't be gathered
|
||||
if _, randErr := rand.Reader.Read(id); randErr != nil {
|
||||
panic(fmt.Errorf("xid: cannot get hostname nor generate a random number: %v; %v", err, randErr))
|
||||
}
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// randInt generates a random uint32
|
||||
func randInt() uint32 {
|
||||
b := make([]byte, 3)
|
||||
if _, err := rand.Reader.Read(b); err != nil {
|
||||
panic(fmt.Errorf("xid: cannot generate random number: %v;", err))
|
||||
}
|
||||
return uint32(b[0])<<16 | uint32(b[1])<<8 | uint32(b[2])
|
||||
}
|
||||
|
||||
// New generates a globally unique ID
|
||||
func New() ID {
|
||||
return NewWithTime(time.Now())
|
||||
}
|
||||
|
||||
// NewWithTime generates a globally unique ID with the passed in time
|
||||
func NewWithTime(t time.Time) ID {
|
||||
var id ID
|
||||
// Timestamp, 4 bytes, big endian
|
||||
binary.BigEndian.PutUint32(id[:], uint32(t.Unix()))
|
||||
// Machine, first 3 bytes of md5(hostname)
|
||||
id[4] = machineID[0]
|
||||
id[5] = machineID[1]
|
||||
id[6] = machineID[2]
|
||||
// Pid, 2 bytes, specs don't specify endianness, but we use big endian.
|
||||
id[7] = byte(pid >> 8)
|
||||
id[8] = byte(pid)
|
||||
// Increment, 3 bytes, big endian
|
||||
i := atomic.AddUint32(&objectIDCounter, 1)
|
||||
id[9] = byte(i >> 16)
|
||||
id[10] = byte(i >> 8)
|
||||
id[11] = byte(i)
|
||||
return id
|
||||
}
|
||||
|
||||
// FromString reads an ID from its string representation
|
||||
func FromString(id string) (ID, error) {
|
||||
i := &ID{}
|
||||
err := i.UnmarshalText([]byte(id))
|
||||
return *i, err
|
||||
}
|
||||
|
||||
// String returns a base32 hex lowercased with no padding representation of the id (char set is 0-9, a-v).
|
||||
func (id ID) String() string {
|
||||
text := make([]byte, encodedLen)
|
||||
encode(text, id[:])
|
||||
return string(text)
|
||||
}
|
||||
|
||||
// MarshalText implements encoding/text TextMarshaler interface
|
||||
func (id ID) MarshalText() ([]byte, error) {
|
||||
text := make([]byte, encodedLen)
|
||||
encode(text, id[:])
|
||||
return text, nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements encoding/json Marshaler interface
|
||||
func (id ID) MarshalJSON() ([]byte, error) {
|
||||
if id.IsNil() {
|
||||
return []byte("null"), nil
|
||||
}
|
||||
text, err := id.MarshalText()
|
||||
return []byte(`"` + string(text) + `"`), err
|
||||
}
|
||||
|
||||
// encode by unrolling the stdlib base32 algorithm + removing all safe checks
|
||||
func encode(dst, id []byte) {
|
||||
dst[0] = encoding[id[0]>>3]
|
||||
dst[1] = encoding[(id[1]>>6)&0x1F|(id[0]<<2)&0x1F]
|
||||
dst[2] = encoding[(id[1]>>1)&0x1F]
|
||||
dst[3] = encoding[(id[2]>>4)&0x1F|(id[1]<<4)&0x1F]
|
||||
dst[4] = encoding[id[3]>>7|(id[2]<<1)&0x1F]
|
||||
dst[5] = encoding[(id[3]>>2)&0x1F]
|
||||
dst[6] = encoding[id[4]>>5|(id[3]<<3)&0x1F]
|
||||
dst[7] = encoding[id[4]&0x1F]
|
||||
dst[8] = encoding[id[5]>>3]
|
||||
dst[9] = encoding[(id[6]>>6)&0x1F|(id[5]<<2)&0x1F]
|
||||
dst[10] = encoding[(id[6]>>1)&0x1F]
|
||||
dst[11] = encoding[(id[7]>>4)&0x1F|(id[6]<<4)&0x1F]
|
||||
dst[12] = encoding[id[8]>>7|(id[7]<<1)&0x1F]
|
||||
dst[13] = encoding[(id[8]>>2)&0x1F]
|
||||
dst[14] = encoding[(id[9]>>5)|(id[8]<<3)&0x1F]
|
||||
dst[15] = encoding[id[9]&0x1F]
|
||||
dst[16] = encoding[id[10]>>3]
|
||||
dst[17] = encoding[(id[11]>>6)&0x1F|(id[10]<<2)&0x1F]
|
||||
dst[18] = encoding[(id[11]>>1)&0x1F]
|
||||
dst[19] = encoding[(id[11]<<4)&0x1F]
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding/text TextUnmarshaler interface
|
||||
func (id *ID) UnmarshalText(text []byte) error {
|
||||
if len(text) != encodedLen {
|
||||
return ErrInvalidID
|
||||
}
|
||||
for _, c := range text {
|
||||
if dec[c] == 0xFF {
|
||||
return ErrInvalidID
|
||||
}
|
||||
}
|
||||
decode(id, text)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements encoding/json Unmarshaler interface
|
||||
func (id *ID) UnmarshalJSON(b []byte) error {
|
||||
s := string(b)
|
||||
if s == "null" {
|
||||
*id = nilID
|
||||
return nil
|
||||
}
|
||||
return id.UnmarshalText(b[1 : len(b)-1])
|
||||
}
|
||||
|
||||
// decode by unrolling the stdlib base32 algorithm + removing all safe checks
|
||||
func decode(id *ID, src []byte) {
|
||||
id[0] = dec[src[0]]<<3 | dec[src[1]]>>2
|
||||
id[1] = dec[src[1]]<<6 | dec[src[2]]<<1 | dec[src[3]]>>4
|
||||
id[2] = dec[src[3]]<<4 | dec[src[4]]>>1
|
||||
id[3] = dec[src[4]]<<7 | dec[src[5]]<<2 | dec[src[6]]>>3
|
||||
id[4] = dec[src[6]]<<5 | dec[src[7]]
|
||||
id[5] = dec[src[8]]<<3 | dec[src[9]]>>2
|
||||
id[6] = dec[src[9]]<<6 | dec[src[10]]<<1 | dec[src[11]]>>4
|
||||
id[7] = dec[src[11]]<<4 | dec[src[12]]>>1
|
||||
id[8] = dec[src[12]]<<7 | dec[src[13]]<<2 | dec[src[14]]>>3
|
||||
id[9] = dec[src[14]]<<5 | dec[src[15]]
|
||||
id[10] = dec[src[16]]<<3 | dec[src[17]]>>2
|
||||
id[11] = dec[src[17]]<<6 | dec[src[18]]<<1 | dec[src[19]]>>4
|
||||
}
|
||||
|
||||
// Time returns the timestamp part of the id.
|
||||
// It's a runtime error to call this method with an invalid id.
|
||||
func (id ID) Time() time.Time {
|
||||
// First 4 bytes of ObjectId is 32-bit big-endian seconds from epoch.
|
||||
secs := int64(binary.BigEndian.Uint32(id[0:4]))
|
||||
return time.Unix(secs, 0)
|
||||
}
|
||||
|
||||
// Machine returns the 3-byte machine id part of the id.
|
||||
// It's a runtime error to call this method with an invalid id.
|
||||
func (id ID) Machine() []byte {
|
||||
return id[4:7]
|
||||
}
|
||||
|
||||
// Pid returns the process id part of the id.
|
||||
// It's a runtime error to call this method with an invalid id.
|
||||
func (id ID) Pid() uint16 {
|
||||
return binary.BigEndian.Uint16(id[7:9])
|
||||
}
|
||||
|
||||
// Counter returns the incrementing value part of the id.
|
||||
// It's a runtime error to call this method with an invalid id.
|
||||
func (id ID) Counter() int32 {
|
||||
b := id[9:12]
|
||||
// Counter is stored as big-endian 3-byte value
|
||||
return int32(uint32(b[0])<<16 | uint32(b[1])<<8 | uint32(b[2]))
|
||||
}
|
||||
|
||||
// Value implements the driver.Valuer interface.
|
||||
func (id ID) Value() (driver.Value, error) {
|
||||
if id.IsNil() {
|
||||
return nil, nil
|
||||
}
|
||||
b, err := id.MarshalText()
|
||||
return string(b), err
|
||||
}
|
||||
|
||||
// Scan implements the sql.Scanner interface.
|
||||
func (id *ID) Scan(value interface{}) (err error) {
|
||||
switch val := value.(type) {
|
||||
case string:
|
||||
return id.UnmarshalText([]byte(val))
|
||||
case []byte:
|
||||
return id.UnmarshalText(val)
|
||||
case nil:
|
||||
*id = nilID
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("xid: scanning unsupported type: %T", value)
|
||||
}
|
||||
}
|
||||
|
||||
// IsNil Returns true if this is a "nil" ID
|
||||
func (id ID) IsNil() bool {
|
||||
return id == nilID
|
||||
}
|
||||
|
||||
// NilID returns a zero value for `xid.ID`.
|
||||
func NilID() ID {
|
||||
return nilID
|
||||
}
|
||||
|
||||
// Bytes returns the byte array representation of `ID`
|
||||
func (id ID) Bytes() []byte {
|
||||
return id[:]
|
||||
}
|
||||
|
||||
// FromBytes convert the byte array representation of `ID` back to `ID`
|
||||
func FromBytes(b []byte) (ID, error) {
|
||||
var id ID
|
||||
if len(b) != rawLen {
|
||||
return id, ErrInvalidID
|
||||
}
|
||||
copy(id[:], b)
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// Compare returns an integer comparing two IDs. It behaves just like `bytes.Compare`.
|
||||
// The result will be 0 if two IDs are identical, -1 if current id is less than the other one,
|
||||
// and 1 if current id is greater than the other.
|
||||
func (id ID) Compare(other ID) int {
|
||||
return bytes.Compare(id[:], other[:])
|
||||
}
|
||||
|
||||
type sorter []ID
|
||||
|
||||
func (s sorter) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s sorter) Less(i, j int) bool {
|
||||
return s[i].Compare(s[j]) < 0
|
||||
}
|
||||
|
||||
func (s sorter) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
// Sort sorts an array of IDs inplace.
|
||||
// It works by wrapping `[]ID` and use `sort.Sort`.
|
||||
func Sort(ids []ID) {
|
||||
sort.Sort(sorter(ids))
|
||||
}
|
396
core/uniqueid/xid/id_test.go
Executable file
396
core/uniqueid/xid/id_test.go
Executable file
|
@ -0,0 +1,396 @@
|
|||
package xid
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type IDParts struct {
|
||||
id ID
|
||||
timestamp int64
|
||||
machine []byte
|
||||
pid uint16
|
||||
counter int32
|
||||
}
|
||||
|
||||
var IDs = []IDParts{
|
||||
IDParts{
|
||||
ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9},
|
||||
1300816219,
|
||||
[]byte{0x60, 0xf4, 0x86},
|
||||
0xe428,
|
||||
4271561,
|
||||
},
|
||||
IDParts{
|
||||
ID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
0,
|
||||
[]byte{0x00, 0x00, 0x00},
|
||||
0x0000,
|
||||
0,
|
||||
},
|
||||
IDParts{
|
||||
ID{0x00, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x00, 0x00, 0x01},
|
||||
0,
|
||||
[]byte{0xaa, 0xbb, 0xcc},
|
||||
0xddee,
|
||||
1,
|
||||
},
|
||||
}
|
||||
|
||||
func TestIDPartsExtraction(t *testing.T) {
|
||||
for i, v := range IDs {
|
||||
t.Run(fmt.Sprintf("Test%d", i), func(t *testing.T) {
|
||||
if got, want := v.id.Time(), time.Unix(v.timestamp, 0); got != want {
|
||||
t.Errorf("Time() = %v, want %v", got, want)
|
||||
}
|
||||
if got, want := v.id.Machine(), v.machine; !bytes.Equal(got, want) {
|
||||
t.Errorf("Machine() = %v, want %v", got, want)
|
||||
}
|
||||
if got, want := v.id.Pid(), v.pid; got != want {
|
||||
t.Errorf("Pid() = %v, want %v", got, want)
|
||||
}
|
||||
if got, want := v.id.Counter(), v.counter; got != want {
|
||||
t.Errorf("Counter() = %v, want %v", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
// Generate 10 ids
|
||||
ids := make([]ID, 10)
|
||||
for i := 0; i < 10; i++ {
|
||||
ids[i] = New()
|
||||
}
|
||||
for i := 1; i < 10; i++ {
|
||||
prevID := ids[i-1]
|
||||
id := ids[i]
|
||||
// Test for uniqueness among all other 9 generated ids
|
||||
for j, tid := range ids {
|
||||
if j != i {
|
||||
if id.Compare(tid) == 0 {
|
||||
t.Errorf("generated ID is not unique (%d/%d)", i, j)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check that timestamp was incremented and is within 30 seconds of the previous one
|
||||
secs := id.Time().Sub(prevID.Time()).Seconds()
|
||||
if secs < 0 || secs > 30 {
|
||||
t.Error("wrong timestamp in generated ID")
|
||||
}
|
||||
// Check that machine ids are the same
|
||||
if !bytes.Equal(id.Machine(), prevID.Machine()) {
|
||||
t.Error("machine ID not equal")
|
||||
}
|
||||
// Check that pids are the same
|
||||
if id.Pid() != prevID.Pid() {
|
||||
t.Error("pid not equal")
|
||||
}
|
||||
// Test for proper increment
|
||||
if got, want := int(id.Counter()-prevID.Counter()), 1; got != want {
|
||||
t.Errorf("wrong increment in generated ID, delta=%v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIDString(t *testing.T) {
|
||||
id := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
|
||||
if got, want := id.String(), "9m4e2mr0ui3e8a215n4g"; got != want {
|
||||
t.Errorf("String() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFromString(t *testing.T) {
|
||||
got, err := FromString("9m4e2mr0ui3e8a215n4g")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
|
||||
if got != want {
|
||||
t.Errorf("FromString() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFromStringInvalid(t *testing.T) {
|
||||
_, err := FromString("invalid")
|
||||
if err != ErrInvalidID {
|
||||
t.Errorf("FromString(invalid) err=%v, want %v", err, ErrInvalidID)
|
||||
}
|
||||
}
|
||||
|
||||
type jsonType struct {
|
||||
ID *ID
|
||||
Str string
|
||||
}
|
||||
|
||||
func TestIDJSONMarshaling(t *testing.T) {
|
||||
id := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
|
||||
v := jsonType{ID: &id, Str: "test"}
|
||||
data, err := json.Marshal(&v)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := string(data), `{"ID":"9m4e2mr0ui3e8a215n4g","Str":"test"}`; got != want {
|
||||
t.Errorf("json.Marshal() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIDJSONUnmarshaling(t *testing.T) {
|
||||
data := []byte(`{"ID":"9m4e2mr0ui3e8a215n4g","Str":"test"}`)
|
||||
v := jsonType{}
|
||||
err := json.Unmarshal(data, &v)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
|
||||
if got := *v.ID; got.Compare(want) != 0 {
|
||||
t.Errorf("json.Unmarshal() = %v, want %v", got, want)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIDJSONUnmarshalingError(t *testing.T) {
|
||||
v := jsonType{}
|
||||
err := json.Unmarshal([]byte(`{"ID":"9M4E2MR0UI3E8A215N4G"}`), &v)
|
||||
if err != ErrInvalidID {
|
||||
t.Errorf("json.Unmarshal() err=%v, want %v", err, ErrInvalidID)
|
||||
}
|
||||
err = json.Unmarshal([]byte(`{"ID":"TYjhW2D0huQoQS"}`), &v)
|
||||
if err != ErrInvalidID {
|
||||
t.Errorf("json.Unmarshal() err=%v, want %v", err, ErrInvalidID)
|
||||
}
|
||||
err = json.Unmarshal([]byte(`{"ID":"TYjhW2D0huQoQS3kdk"}`), &v)
|
||||
if err != ErrInvalidID {
|
||||
t.Errorf("json.Unmarshal() err=%v, want %v", err, ErrInvalidID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIDDriverValue(t *testing.T) {
|
||||
id := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
|
||||
got, err := id.Value()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if want := "9m4e2mr0ui3e8a215n4g"; got != want {
|
||||
t.Errorf("Value() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIDDriverScan(t *testing.T) {
|
||||
got := ID{}
|
||||
err := got.Scan("9m4e2mr0ui3e8a215n4g")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
|
||||
if got.Compare(want) != 0 {
|
||||
t.Errorf("Scan() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIDDriverScanError(t *testing.T) {
|
||||
id := ID{}
|
||||
if got, want := id.Scan(0), errors.New("xid: scanning unsupported type: int"); !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("Scan() err=%v, want %v", got, want)
|
||||
}
|
||||
if got, want := id.Scan("0"), ErrInvalidID; got != want {
|
||||
t.Errorf("Scan() err=%v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIDDriverScanByteFromDatabase(t *testing.T) {
|
||||
got := ID{}
|
||||
bs := []byte("9m4e2mr0ui3e8a215n4g")
|
||||
err := got.Scan(bs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
|
||||
if got.Compare(want) != 0 {
|
||||
t.Errorf("Scan() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNew(b *testing.B) {
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_ = New()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkNewString(b *testing.B) {
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_ = New().String()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkFromString(b *testing.B) {
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, _ = FromString("9m4e2mr0ui3e8a215n4g")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// func BenchmarkUUIDv1(b *testing.B) {
|
||||
// b.RunParallel(func(pb *testing.PB) {
|
||||
// for pb.Next() {
|
||||
// _ = uuid.NewV1().String()
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// func BenchmarkUUIDv4(b *testing.B) {
|
||||
// b.RunParallel(func(pb *testing.PB) {
|
||||
// for pb.Next() {
|
||||
// _ = uuid.NewV4().String()
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
func TestID_IsNil(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
id ID
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "ID not nil",
|
||||
id: New(),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "Nil ID",
|
||||
id: ID{},
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got, want := tt.id.IsNil(), tt.want; got != want {
|
||||
t.Errorf("IsNil() = %v, want %v", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNilID(t *testing.T) {
|
||||
got := ID{}
|
||||
if want := NilID(); !reflect.DeepEqual(got, want) {
|
||||
t.Error("NilID() not equal ID{}")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNilID_IsNil(t *testing.T) {
|
||||
if !NilID().IsNil() {
|
||||
t.Error("NilID().IsNil() is not true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFromBytes_Invariant(t *testing.T) {
|
||||
want := New()
|
||||
got, err := FromBytes(want.Bytes())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.Compare(want) != 0 {
|
||||
t.Error("FromBytes(id.Bytes()) != id")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFromBytes_InvalidBytes(t *testing.T) {
|
||||
cases := []struct {
|
||||
length int
|
||||
shouldFail bool
|
||||
}{
|
||||
{11, true},
|
||||
{12, false},
|
||||
{13, true},
|
||||
}
|
||||
for _, c := range cases {
|
||||
b := make([]byte, c.length, c.length)
|
||||
_, err := FromBytes(b)
|
||||
if got, want := err != nil, c.shouldFail; got != want {
|
||||
t.Errorf("FromBytes() error got %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestID_Compare(t *testing.T) {
|
||||
pairs := []struct {
|
||||
left ID
|
||||
right ID
|
||||
expected int
|
||||
}{
|
||||
{IDs[1].id, IDs[0].id, -1},
|
||||
{ID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, IDs[2].id, -1},
|
||||
{IDs[0].id, IDs[0].id, 0},
|
||||
}
|
||||
for _, p := range pairs {
|
||||
if p.expected != p.left.Compare(p.right) {
|
||||
t.Errorf("%s Compare to %s should return %d", p.left, p.right, p.expected)
|
||||
}
|
||||
if -1*p.expected != p.right.Compare(p.left) {
|
||||
t.Errorf("%s Compare to %s should return %d", p.right, p.left, -1*p.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var IDList = []ID{IDs[0].id, IDs[1].id, IDs[2].id}
|
||||
|
||||
func TestSorter_Len(t *testing.T) {
|
||||
if got, want := sorter([]ID{}).Len(), 0; got != want {
|
||||
t.Errorf("Len() %v, want %v", got, want)
|
||||
}
|
||||
if got, want := sorter(IDList).Len(), 3; got != want {
|
||||
t.Errorf("Len() %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSorter_Less(t *testing.T) {
|
||||
sorter := sorter(IDList)
|
||||
if !sorter.Less(1, 0) {
|
||||
t.Errorf("Less(1, 0) not true")
|
||||
}
|
||||
if sorter.Less(2, 1) {
|
||||
t.Errorf("Less(2, 1) true")
|
||||
}
|
||||
if sorter.Less(0, 0) {
|
||||
t.Errorf("Less(0, 0) true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSorter_Swap(t *testing.T) {
|
||||
ids := make([]ID, 0)
|
||||
ids = append(ids, IDList...)
|
||||
sorter := sorter(ids)
|
||||
sorter.Swap(0, 1)
|
||||
if got, want := ids[0], IDList[1]; !reflect.DeepEqual(got, want) {
|
||||
t.Error("ids[0] != IDList[1]")
|
||||
}
|
||||
if got, want := ids[1], IDList[0]; !reflect.DeepEqual(got, want) {
|
||||
t.Error("ids[1] != IDList[0]")
|
||||
}
|
||||
sorter.Swap(2, 2)
|
||||
if got, want := ids[2], IDList[2]; !reflect.DeepEqual(got, want) {
|
||||
t.Error("ids[2], IDList[2]")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSort(t *testing.T) {
|
||||
ids := make([]ID, 0)
|
||||
ids = append(ids, IDList...)
|
||||
Sort(ids)
|
||||
if got, want := ids, []ID{IDList[1], IDList[2], IDList[0]}; !reflect.DeepEqual(got, want) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@
|
|||
// - http://www.slideshare.net/davegardnerisme/unique-id-generation-in-distributed-systems
|
||||
// - https://en.wikipedia.org/wiki/Universally_unique_identifier
|
||||
// - https://blog.twitter.com/2010/announcing-snowflake
|
||||
package xid
|
||||
package xid16
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
186
domain/backup/endpoint.go
Normal file
186
domain/backup/endpoint.go
Normal file
|
@ -0,0 +1,186 @@
|
|||
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
|
||||
//
|
||||
// This software (Documize Community Edition) is licensed under
|
||||
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
//
|
||||
// You can operate outside the AGPL restrictions by purchasing
|
||||
// Documize Enterprise Edition and obtaining a commercial license
|
||||
// by contacting <sales@documize.com>.
|
||||
//
|
||||
// https://documize.com
|
||||
|
||||
package backup
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/documize/community/core/env"
|
||||
"github.com/documize/community/core/response"
|
||||
"github.com/documize/community/core/streamutil"
|
||||
"github.com/documize/community/core/uniqueid"
|
||||
"github.com/documize/community/domain"
|
||||
indexer "github.com/documize/community/domain/search"
|
||||
"github.com/documize/community/domain/store"
|
||||
)
|
||||
|
||||
// Handler contains the runtime information such as logging and database.
|
||||
type Handler struct {
|
||||
Runtime *env.Runtime
|
||||
Store *store.Store
|
||||
Indexer indexer.Indexer
|
||||
}
|
||||
|
||||
// Backup generates binary file of all instance settings and contents.
|
||||
// The content is pulled directly from the database and marshalled to JSON.
|
||||
// A zip file is then sent to the caller.
|
||||
func (h *Handler) Backup(w http.ResponseWriter, r *http.Request) {
|
||||
method := "system.backup"
|
||||
ctx := domain.GetRequestContext(r)
|
||||
|
||||
if !ctx.Administrator {
|
||||
response.WriteForbiddenError(w)
|
||||
h.Runtime.Log.Info(fmt.Sprintf("Non-admin attempted system backup operation (user ID: %s)", ctx.UserID))
|
||||
return
|
||||
}
|
||||
|
||||
defer streamutil.Close(r.Body)
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
response.WriteBadRequestError(w, method, err.Error())
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
spec := backupSpec{}
|
||||
err = json.Unmarshal(body, &spec)
|
||||
if err != nil {
|
||||
response.WriteBadRequestError(w, method, err.Error())
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
// data, err := backup(ctx, *h.Store, spec)
|
||||
// if err != nil {
|
||||
// response.WriteServerError(w, method, err)
|
||||
// h.Runtime.Log.Error(method, err)
|
||||
// return
|
||||
// }
|
||||
|
||||
// Filename is current timestamp
|
||||
fn := fmt.Sprintf("dmz-backup-%s.zip", uniqueid.Generate())
|
||||
|
||||
ziptest(fn)
|
||||
|
||||
bb, err := ioutil.ReadFile(fn)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/zip")
|
||||
w.Header().Set("Content-Disposition", `attachment; filename="`+fn+`" ; `+`filename*="`+fn+`"`)
|
||||
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(bb)))
|
||||
w.Header().Set("x-documize-filename", fn)
|
||||
|
||||
x, err := w.Write(bb)
|
||||
if err != nil {
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
h.Runtime.Log.Info(fmt.Sprintf("Backup completed for %s by %s, size %d", ctx.OrgID, ctx.UserID, x))
|
||||
}
|
||||
|
||||
type backupSpec struct {
|
||||
}
|
||||
|
||||
func backup(ctx domain.RequestContext, s store.Store, spec backupSpec) (file []byte, err error) {
|
||||
buf := new(bytes.Buffer)
|
||||
zw := zip.NewWriter(buf)
|
||||
|
||||
// Add some files to the archive.
|
||||
var files = []struct {
|
||||
Name, Body string
|
||||
}{
|
||||
{"readme.txt", "This archive contains some text files."},
|
||||
{"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"},
|
||||
{"todo.txt", "Get animal handling licence.\nWrite more examples."},
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
f, err := zw.Create(file.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = f.Write([]byte(file.Body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure to check the error on Close.
|
||||
err = zw.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func ziptest(filename string) {
|
||||
// Create a file to write the archive buffer to
|
||||
// Could also use an in memory buffer.
|
||||
outFile, err := os.Create(filename)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer outFile.Close()
|
||||
|
||||
// Create a zip writer on top of the file writer
|
||||
zipWriter := zip.NewWriter(outFile)
|
||||
|
||||
// Add files to archive
|
||||
// We use some hard coded data to demonstrate,
|
||||
// but you could iterate through all the files
|
||||
// in a directory and pass the name and contents
|
||||
// of each file, or you can take data from your
|
||||
// program and write it write in to the archive
|
||||
// without
|
||||
var filesToArchive = []struct {
|
||||
Name, Body string
|
||||
}{
|
||||
{"test.txt", "String contents of file"},
|
||||
{"test2.txt", "\x61\x62\x63\n"},
|
||||
}
|
||||
|
||||
// Create and write files to the archive, which in turn
|
||||
// are getting written to the underlying writer to the
|
||||
// .zip file we created at the beginning
|
||||
for _, file := range filesToArchive {
|
||||
fileWriter, err := zipWriter.Create(file.Name)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
_, err = fileWriter.Write([]byte(file.Body))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
err = zipWriter.Close()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
|
@ -58,7 +58,8 @@ func (h *Handler) Meta(w http.ResponseWriter, r *http.Request) {
|
|||
data.AuthConfig = org.AuthConfig
|
||||
data.MaxTags = org.MaxTags
|
||||
data.Version = h.Runtime.Product.Version
|
||||
data.Edition = h.Runtime.Product.License.Edition
|
||||
data.Revision = h.Runtime.Product.Revision
|
||||
data.Edition = h.Runtime.Product.Edition
|
||||
data.Valid = h.Runtime.Product.License.Valid
|
||||
data.ConversionEndpoint = org.ConversionEndpoint
|
||||
data.License = h.Runtime.Product.License
|
||||
|
|
|
@ -60,7 +60,6 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
response.WriteBadLicense(w)
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.Editor {
|
||||
response.WriteForbiddenError(w)
|
||||
return
|
||||
|
@ -205,11 +204,16 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
// to avoid conflicts.
|
||||
groupChange := make(map[string]string)
|
||||
|
||||
// Store old-to-new document ID mapping for subsequence reference.
|
||||
docMap := make(map[string]string)
|
||||
|
||||
if len(toCopy) > 0 {
|
||||
for _, t := range toCopy {
|
||||
origID := t.RefID
|
||||
|
||||
documentID := uniqueid.Generate()
|
||||
docMap[t.RefID] = documentID
|
||||
|
||||
t.RefID = documentID
|
||||
t.SpaceID = sp.RefID
|
||||
|
||||
|
@ -320,6 +324,72 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// Copy over space categories, associated permissions and document assignments.
|
||||
cats, err := h.Store.Category.GetAllBySpace(ctx, model.CloneID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
catMap := make(map[string]string)
|
||||
for _, ct := range cats {
|
||||
// Store old-to-new category ID mapping for subsequent processing.
|
||||
cid := uniqueid.Generate()
|
||||
catMap[ct.RefID] = cid
|
||||
|
||||
// Get existing user/group permissions for the category to be cloned.
|
||||
cp, err := h.Store.Permission.GetCategoryPermissions(ctx, ct.RefID)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Add cloned category.
|
||||
ct.RefID = cid
|
||||
ct.SpaceID = sp.RefID
|
||||
err = h.Store.Category.Add(ctx, ct)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Add cloned category permissions.
|
||||
for _, p := range cp {
|
||||
p.RefID = cid
|
||||
err = h.Store.Permission.AddPermission(ctx, p)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add cloned category members
|
||||
cm, err := h.Store.Category.GetSpaceCategoryMembership(ctx, model.CloneID)
|
||||
for _, m := range cm {
|
||||
m.RefID = uniqueid.Generate()
|
||||
m.CategoryID = catMap[m.CategoryID]
|
||||
m.DocumentID = docMap[m.DocumentID]
|
||||
m.SpaceID = sp.RefID
|
||||
|
||||
err = h.Store.Category.AssociateDocument(ctx, m)
|
||||
if err != nil {
|
||||
ctx.Transaction.Rollback()
|
||||
response.WriteServerError(w, method, err)
|
||||
h.Runtime.Log.Error(method, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Finish up the clone operations.
|
||||
ctx.Transaction.Commit()
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,6 @@ import (
|
|||
"github.com/documize/community/server/web"
|
||||
)
|
||||
|
||||
var rt env.Runtime
|
||||
|
||||
func main() {
|
||||
// runtime stores server/application level information
|
||||
rt := env.Runtime{}
|
||||
|
@ -42,6 +40,7 @@ func main() {
|
|||
rt.Product.Major = "1"
|
||||
rt.Product.Minor = "71"
|
||||
rt.Product.Patch = "0"
|
||||
rt.Product.Revision = 181004111512
|
||||
rt.Product.Version = fmt.Sprintf("%s.%s.%s", rt.Product.Major, rt.Product.Minor, rt.Product.Patch)
|
||||
rt.Product.Edition = "Community"
|
||||
rt.Product.Title = fmt.Sprintf("%s Edition", rt.Product.Edition)
|
||||
|
|
1332
embed/bindata.go
1332
embed/bindata.go
File diff suppressed because one or more lines are too long
|
@ -27,6 +27,7 @@ export default Service.extend({
|
|||
orgId: '',
|
||||
title: '',
|
||||
version: '',
|
||||
revision: 1000,
|
||||
message: '',
|
||||
edition: 'Community',
|
||||
valid: true,
|
||||
|
|
|
@ -124,7 +124,7 @@
|
|||
<div id="space-add-user-modal" class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">Space Deletion</div>
|
||||
<div class="modal-header">Add User To Space</div>
|
||||
<div class="modal-body">
|
||||
{{input id="user-search" type="text" class="form-control mousetrap" placeholder="Search for users by firstname, lastname, email" value=searchText key-up=(action 'onSearch')}}
|
||||
{{#each filteredUsers as |user|}}
|
||||
|
|
|
@ -172,6 +172,9 @@
|
|||
<div class="version">
|
||||
{{appMeta.version}}
|
||||
</div>
|
||||
<div class="version">
|
||||
Build {{appMeta.revision}}
|
||||
</div>
|
||||
<div class="dotcom">
|
||||
<a href="https://documize.com">https://documize.com</a>
|
||||
</div>
|
||||
|
@ -183,7 +186,7 @@
|
|||
<br/>
|
||||
<br/> This software (Documize Community Edition) is licensed under
|
||||
<a href="http://www.gnu.org/licenses/agpl-3.0.en.html">GNU AGPL v3</a>
|
||||
You can operate outside the AGPL restrictions by purchasing Documize Enterprise Edition and obtaining a commercial licenseby
|
||||
You can operate outside the AGPL restrictions by purchasing Documize Enterprise Edition and obtaining a commercial license by
|
||||
contacting
|
||||
<a href="mailto:sales@documize.com">sales@documize.com</a>
|
||||
</div>
|
||||
|
|
|
@ -36,6 +36,7 @@ type SiteMeta struct {
|
|||
AuthProvider string `json:"authProvider"`
|
||||
AuthConfig string `json:"authConfig"`
|
||||
Version string `json:"version"`
|
||||
Revision int `json:"revision"`
|
||||
MaxTags int `json:"maxTags"`
|
||||
Edition string `json:"edition"`
|
||||
Valid bool `json:"valid"`
|
||||
|
|
|
@ -30,7 +30,7 @@ var testHost string // used during automated testing
|
|||
|
||||
// Start router to handle all HTTP traffic.
|
||||
func Start(rt *env.Runtime, s *store.Store, ready chan struct{}) {
|
||||
rt.Log.Info(fmt.Sprintf("Product: %s version %s", rt.Product.Title, rt.Product.Version))
|
||||
rt.Log.Info(fmt.Sprintf("Product: %s version %s (build %d)", rt.Product.Title, rt.Product.Version, rt.Product.Revision))
|
||||
|
||||
// decide which mode to serve up
|
||||
switch rt.Flags.SiteMode {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue