From 876e03b78b2a063b02eae0127a65608e446296a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Sat, 30 May 2026 14:23:10 +0300 Subject: [PATCH] =?UTF-8?q?research:=20payg-report=20=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D0=BA=D0=BE=D0=BF=D0=B8=D1=8F=20=D1=80?= =?UTF-8?q?=D0=B5=D0=BF=D1=8B=20(=D0=B2=D1=81=D0=B5=20=D1=84=D0=B0=D0=B9?= =?UTF-8?q?=D0=BB=D1=8B,=20=D0=B1=D0=B5=D0=B7=20.git)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- research/payg-sso-full/1.cfm | 11 + research/payg-sso-full/Application.cfc | 522 +++++ research/payg-sso-full/etc/2do.txt | 6 + .../payg-sso-full/etc/db/billing_schema.sql | 595 ++++++ .../payg-sso-full/etc/db/billing_schema2.sql | 1766 +++++++++++++++++ .../etc/db/billing_schema_dev.sql | 72 + .../etc/db/billing_schema_s3.sql | 828 ++++++++ .../etc/db/billing_schema_vc.sql | 278 +++ research/payg-sso-full/etc/db/indexes.sql | 9 + research/payg-sso-full/etc/env.json | 8 + research/payg-sso-full/etc/set_env.cmd | 10 + research/payg-sso-full/etc/trash/payg.cfm.bak | 281 +++ .../payg-sso-full/etc/trash/payg2.cfm.bak | 159 ++ .../payg-sso-full/img/Arrow-Left-icon.png | Bin 0 -> 12641 bytes .../payg-sso-full/img/Arrow-left-icon (1).png | Bin 0 -> 6246 bytes research/payg-sso-full/img/DataLime.svg | 47 + research/payg-sso-full/img/Knob-Left-icon.png | Bin 0 -> 1722 bytes research/payg-sso-full/img/a-piece.png | Bin 0 -> 27555 bytes research/payg-sso-full/img/add.gif | Bin 0 -> 69 bytes .../img/alarm-arrow-left-icon.png | Bin 0 -> 24085 bytes .../payg-sso-full/img/alarm-arrow-up-icon.png | Bin 0 -> 24146 bytes research/payg-sso-full/img/arr_dn.png | Bin 0 -> 174 bytes research/payg-sso-full/img/arr_dn1.png | Bin 0 -> 173 bytes research/payg-sso-full/img/arr_dn2.png | Bin 0 -> 173 bytes research/payg-sso-full/img/arr_up.png | Bin 0 -> 180 bytes research/payg-sso-full/img/arr_up1.png | Bin 0 -> 179 bytes research/payg-sso-full/img/arr_up2.png | Bin 0 -> 180 bytes .../payg-sso-full/img/arrow-left-icon (2).png | Bin 0 -> 1388 bytes research/payg-sso-full/img/asvc.jpg | Bin 0 -> 14080 bytes research/payg-sso-full/img/complex.png | Bin 0 -> 255 bytes research/payg-sso-full/img/component.png | Bin 0 -> 9133 bytes research/payg-sso-full/img/component.svg | 16 + research/payg-sso-full/img/deer.bk.png | Bin 0 -> 46591 bytes research/payg-sso-full/img/deer.png | Bin 0 -> 30505 bytes research/payg-sso-full/img/del.gif | Bin 0 -> 141 bytes research/payg-sso-full/img/del16.png | Bin 0 -> 222 bytes research/payg-sso-full/img/del2.png | Bin 0 -> 1317 bytes research/payg-sso-full/img/dit.png | Bin 0 -> 2287 bytes research/payg-sso-full/img/dit_m.png | Bin 0 -> 1535 bytes research/payg-sso-full/img/dit_m1.png | Bin 0 -> 1530 bytes research/payg-sso-full/img/download.png | Bin 0 -> 1023 bytes research/payg-sso-full/img/edit.gif | Bin 0 -> 889 bytes research/payg-sso-full/img/edit.gif.bk | Bin 0 -> 81 bytes research/payg-sso-full/img/favicon.ico | Bin 0 -> 15086 bytes research/payg-sso-full/img/favicon1.ico | Bin 0 -> 15086 bytes research/payg-sso-full/img/json.svg | 16 + research/payg-sso-full/img/logo.png | Bin 0 -> 14089 bytes research/payg-sso-full/img/logo0.png | Bin 0 -> 7277 bytes .../payg-sso-full/img/mimetype/document.png | Bin 0 -> 431 bytes research/payg-sso-full/img/mimetype/excel.png | Bin 0 -> 725 bytes .../payg-sso-full/img/mimetype/ficon_pptx.gif | Bin 0 -> 996 bytes research/payg-sso-full/img/mimetype/html.png | Bin 0 -> 743 bytes research/payg-sso-full/img/mimetype/image.png | Bin 0 -> 972 bytes .../payg-sso-full/img/mimetype/image_.png | Bin 0 -> 517 bytes research/payg-sso-full/img/mimetype/pdf.png | Bin 0 -> 665 bytes .../payg-sso-full/img/mimetype/powerpoint.png | Bin 0 -> 692 bytes research/payg-sso-full/img/mimetype/text.png | Bin 0 -> 271 bytes research/payg-sso-full/img/mimetype/word.png | Bin 0 -> 691 bytes research/payg-sso-full/img/minus.gif | Bin 0 -> 71 bytes research/payg-sso-full/img/new.gif | Bin 0 -> 71 bytes research/payg-sso-full/img/ok.png | Bin 0 -> 537 bytes research/payg-sso-full/img/paperclip.gif | Bin 0 -> 305 bytes research/payg-sso-full/img/piece.png | Bin 0 -> 350 bytes research/payg-sso-full/img/portlet_dot.gif | Bin 0 -> 346 bytes research/payg-sso-full/img/redmult.png | Bin 0 -> 1000 bytes research/payg-sso-full/img/redmult16.png | Bin 0 -> 1044 bytes research/payg-sso-full/img/sarrow.bk.gif | Bin 0 -> 54 bytes research/payg-sso-full/img/sarrow.gif | Bin 0 -> 54 bytes research/payg-sso-full/img/save.gif | Bin 0 -> 103 bytes research/payg-sso-full/img/search.gif | Bin 0 -> 241 bytes research/payg-sso-full/img/search_icon.png | Bin 0 -> 362 bytes research/payg-sso-full/img/simple.png | Bin 0 -> 243 bytes research/payg-sso-full/img/svc.jpg | Bin 0 -> 99643 bytes research/payg-sso-full/img/up.gif | Bin 0 -> 51 bytes research/payg-sso-full/img/view.gif | Bin 0 -> 84 bytes research/payg-sso-full/img/xls.gif | Bin 0 -> 990 bytes research/payg-sso-full/inc/functions.cfm | 358 ++++ research/payg-sso-full/inc/menu.cfm | 16 + research/payg-sso-full/index.cfm | 37 + research/payg-sso-full/js/jquery.min.js | 4 + .../js/jquery.searchabledropdown.js | 3 + research/payg-sso-full/json.cfm | 94 + research/payg-sso-full/layout/attribute.cfm | 33 + research/payg-sso-full/layout/column_head.cfm | 43 + .../payg-sso-full/layout/detail_buttons.cfm | 10 + research/payg-sso-full/layout/detail_line.cfm | 10 + .../payg-sso-full/layout/filter_buttons.cfm | 8 + research/payg-sso-full/layout/filter_link.cfm | 24 + research/payg-sso-full/layout/grid_head.cfm | 18 + .../payg-sso-full/layout/grid_summary.cfm | 82 + research/payg-sso-full/layout/json.cfm | 99 + .../payg-sso-full/layout/language_switch.cfm | 9 + research/payg-sso-full/layout/page.cfm | 240 +++ .../payg-sso-full/layout/render_query.cfm | 19 + research/payg-sso-full/layout/xls.cfm | 55 + research/payg-sso-full/layout/xlshtm.cfm | 49 + research/payg-sso-full/layout/xml.cfm | 239 +++ research/payg-sso-full/lib/ac.cfm | 79 + .../payg-sso-full/lib/contenttype_icon.cfm | 12 + .../payg-sso-full/lib/controls/checkbox.cfm | 23 + .../payg-sso-full/lib/controls/column.cfm | 30 + .../lib/controls/column_head.cfm | 46 + research/payg-sso-full/lib/controls/combo.cfm | 178 ++ research/payg-sso-full/lib/controls/date.cfm | 21 + .../payg-sso-full/lib/controls/datetime.cfm | 29 + .../lib/controls/detail_buttons.cfm | 18 + .../payg-sso-full/lib/controls/grid_head.cfm | 18 + .../payg-sso-full/lib/controls/link_add.cfm | 11 + .../payg-sso-full/lib/controls/link_del.cfm | 10 + .../payg-sso-full/lib/controls/link_edit.cfm | 9 + .../payg-sso-full/lib/controls/link_view.cfm | 6 + .../lib/controls/link_view_edit.cfm | 9 + .../payg-sso-full/lib/controls/menu_item.cfm | 25 + .../payg-sso-full/lib/controls/nowbutton.cfm | 6 + .../lib/controls/order_arrows.cfm | 36 + .../payg-sso-full/lib/controls/paginator.cfm | 80 + research/payg-sso-full/lib/controls/table.cfm | 154 ++ research/payg-sso-full/lib/controls/td.cfm | 15 + research/payg-sso-full/lib/controls/text.cfm | 20 + research/payg-sso-full/lib/controls/th.cfm | 6 + research/payg-sso-full/lib/controls/time.cfm | 21 + research/payg-sso-full/lib/data/bean.cfm | 401 ++++ research/payg-sso-full/lib/data/bean.cfm.bak | 400 ++++ research/payg-sso-full/lib/data/bk/bean.cfm | 398 ++++ .../payg-sso-full/lib/data/bk/bean.cfm.bak | 398 ++++ research/payg-sso-full/lib/data/bk/field.cfm | 24 + .../payg-sso-full/lib/data/bk/field_set.cfm | 41 + research/payg-sso-full/lib/data/bk/param.cfm | 305 +++ research/payg-sso-full/lib/data/del.cfm | 297 +++ .../payg-sso-full/lib/data/del_condition.cfm | 19 + research/payg-sso-full/lib/data/dep_field.cfm | 26 + research/payg-sso-full/lib/data/dep_param.cfm | 9 + .../payg-sso-full/lib/data/dependency.cfm | 56 + .../lib/data/dependency_condition.cfm | 9 + .../lib/data/dependency_field.cfm | 22 + .../lib/data/dependency_from.cfm | 6 + .../lib/data/dependency_order_by.cfm | 6 + research/payg-sso-full/lib/data/field.cfm | 66 + research/payg-sso-full/lib/data/field_set.cfm | 68 + research/payg-sso-full/lib/data/param.cfm | 354 ++++ research/payg-sso-full/lib/data/status.cfc | 43 + .../lib/data/submit_collection.cfm | 59 + .../payg-sso-full/lib/data/submit_param.cfm | 69 + .../payg-sso-full/lib/detail_page_info.cfc | 33 + .../payg-sso-full/lib/dispatch_detail.cfm | 59 + research/payg-sso-full/lib/encodingUtils.cfc | 283 +++ research/payg-sso-full/lib/filter_build.cf_ | 131 ++ research/payg-sso-full/lib/filter_build.cfm | 50 + .../payg-sso-full/lib/filter_page_info.cfc | 9 + research/payg-sso-full/lib/filter_rebuild.cfm | 0 .../payg-sso-full/lib/filter_settings.cfm | 26 + research/payg-sso-full/lib/filterparam.cfm | 180 ++ research/payg-sso-full/lib/form_page_info.cfc | 31 + .../payg-sso-full/lib/generic_page_info.cfc | 39 + research/payg-sso-full/lib/init_settings.cfm | 25 + research/payg-sso-full/lib/jwt.cfc | 262 +++ research/payg-sso-full/lib/location.cfm | 5 + research/payg-sso-full/lib/ls_catch.cfm | 24 + research/payg-sso-full/lib/ls_page_info.cfc | 10 + research/payg-sso-full/lib/menu_item.cfm | 24 + research/payg-sso-full/lib/mimetype_icon.cfm | 11 + research/payg-sso-full/lib/oauth2.cfc | 193 ++ research/payg-sso-full/lib/order_build.cfm | 44 + research/payg-sso-full/lib/prepare_detail.cfm | 26 + research/payg-sso-full/lib/prepare_filter.cfm | 26 + research/payg-sso-full/lib/prepare_form.cfm | 16 + research/payg-sso-full/lib/prepare_ls.cfm | 43 + .../payg-sso-full/lib/rest_api_helper.cfc | 396 ++++ research/payg-sso-full/lib/settings.cfm | 213 ++ research/payg-sso-full/lib/silent.cfm | 9 + research/payg-sso-full/lib/sortparam.cfm | 76 + research/payg-sso-full/lib/track.cfm | 103 + research/payg-sso-full/lib/upload.cfm | 40 + .../lib/utils/authStringBuilder.cfc | 142 ++ research/payg-sso-full/mod/conventions.txt | 3 + research/payg-sso-full/mod/crm_contract.cfm | 94 + research/payg-sso-full/mod/payg.cfm | 428 ++++ research/payg-sso-full/mod/payg.cfm.1.bak | 346 ++++ research/payg-sso-full/payg.cfm | 174 ++ research/payg-sso-full/style/web.css | 321 +++ 180 files changed, 13907 insertions(+) create mode 100644 research/payg-sso-full/1.cfm create mode 100644 research/payg-sso-full/Application.cfc create mode 100644 research/payg-sso-full/etc/2do.txt create mode 100644 research/payg-sso-full/etc/db/billing_schema.sql create mode 100644 research/payg-sso-full/etc/db/billing_schema2.sql create mode 100644 research/payg-sso-full/etc/db/billing_schema_dev.sql create mode 100644 research/payg-sso-full/etc/db/billing_schema_s3.sql create mode 100644 research/payg-sso-full/etc/db/billing_schema_vc.sql create mode 100644 research/payg-sso-full/etc/db/indexes.sql create mode 100644 research/payg-sso-full/etc/env.json create mode 100644 research/payg-sso-full/etc/set_env.cmd create mode 100644 research/payg-sso-full/etc/trash/payg.cfm.bak create mode 100644 research/payg-sso-full/etc/trash/payg2.cfm.bak create mode 100644 research/payg-sso-full/img/Arrow-Left-icon.png create mode 100644 research/payg-sso-full/img/Arrow-left-icon (1).png create mode 100644 research/payg-sso-full/img/DataLime.svg create mode 100644 research/payg-sso-full/img/Knob-Left-icon.png create mode 100644 research/payg-sso-full/img/a-piece.png create mode 100644 research/payg-sso-full/img/add.gif create mode 100644 research/payg-sso-full/img/alarm-arrow-left-icon.png create mode 100644 research/payg-sso-full/img/alarm-arrow-up-icon.png create mode 100644 research/payg-sso-full/img/arr_dn.png create mode 100644 research/payg-sso-full/img/arr_dn1.png create mode 100644 research/payg-sso-full/img/arr_dn2.png create mode 100644 research/payg-sso-full/img/arr_up.png create mode 100644 research/payg-sso-full/img/arr_up1.png create mode 100644 research/payg-sso-full/img/arr_up2.png create mode 100644 research/payg-sso-full/img/arrow-left-icon (2).png create mode 100644 research/payg-sso-full/img/asvc.jpg create mode 100644 research/payg-sso-full/img/complex.png create mode 100644 research/payg-sso-full/img/component.png create mode 100644 research/payg-sso-full/img/component.svg create mode 100644 research/payg-sso-full/img/deer.bk.png create mode 100644 research/payg-sso-full/img/deer.png create mode 100644 research/payg-sso-full/img/del.gif create mode 100644 research/payg-sso-full/img/del16.png create mode 100644 research/payg-sso-full/img/del2.png create mode 100644 research/payg-sso-full/img/dit.png create mode 100644 research/payg-sso-full/img/dit_m.png create mode 100644 research/payg-sso-full/img/dit_m1.png create mode 100644 research/payg-sso-full/img/download.png create mode 100644 research/payg-sso-full/img/edit.gif create mode 100644 research/payg-sso-full/img/edit.gif.bk create mode 100644 research/payg-sso-full/img/favicon.ico create mode 100644 research/payg-sso-full/img/favicon1.ico create mode 100644 research/payg-sso-full/img/json.svg create mode 100644 research/payg-sso-full/img/logo.png create mode 100644 research/payg-sso-full/img/logo0.png create mode 100644 research/payg-sso-full/img/mimetype/document.png create mode 100644 research/payg-sso-full/img/mimetype/excel.png create mode 100644 research/payg-sso-full/img/mimetype/ficon_pptx.gif create mode 100644 research/payg-sso-full/img/mimetype/html.png create mode 100644 research/payg-sso-full/img/mimetype/image.png create mode 100644 research/payg-sso-full/img/mimetype/image_.png create mode 100644 research/payg-sso-full/img/mimetype/pdf.png create mode 100644 research/payg-sso-full/img/mimetype/powerpoint.png create mode 100644 research/payg-sso-full/img/mimetype/text.png create mode 100644 research/payg-sso-full/img/mimetype/word.png create mode 100644 research/payg-sso-full/img/minus.gif create mode 100644 research/payg-sso-full/img/new.gif create mode 100644 research/payg-sso-full/img/ok.png create mode 100644 research/payg-sso-full/img/paperclip.gif create mode 100644 research/payg-sso-full/img/piece.png create mode 100644 research/payg-sso-full/img/portlet_dot.gif create mode 100644 research/payg-sso-full/img/redmult.png create mode 100644 research/payg-sso-full/img/redmult16.png create mode 100644 research/payg-sso-full/img/sarrow.bk.gif create mode 100644 research/payg-sso-full/img/sarrow.gif create mode 100644 research/payg-sso-full/img/save.gif create mode 100644 research/payg-sso-full/img/search.gif create mode 100644 research/payg-sso-full/img/search_icon.png create mode 100644 research/payg-sso-full/img/simple.png create mode 100644 research/payg-sso-full/img/svc.jpg create mode 100644 research/payg-sso-full/img/up.gif create mode 100644 research/payg-sso-full/img/view.gif create mode 100644 research/payg-sso-full/img/xls.gif create mode 100644 research/payg-sso-full/inc/functions.cfm create mode 100644 research/payg-sso-full/inc/menu.cfm create mode 100644 research/payg-sso-full/index.cfm create mode 100644 research/payg-sso-full/js/jquery.min.js create mode 100644 research/payg-sso-full/js/jquery.searchabledropdown.js create mode 100644 research/payg-sso-full/json.cfm create mode 100644 research/payg-sso-full/layout/attribute.cfm create mode 100644 research/payg-sso-full/layout/column_head.cfm create mode 100644 research/payg-sso-full/layout/detail_buttons.cfm create mode 100644 research/payg-sso-full/layout/detail_line.cfm create mode 100644 research/payg-sso-full/layout/filter_buttons.cfm create mode 100644 research/payg-sso-full/layout/filter_link.cfm create mode 100644 research/payg-sso-full/layout/grid_head.cfm create mode 100644 research/payg-sso-full/layout/grid_summary.cfm create mode 100644 research/payg-sso-full/layout/json.cfm create mode 100644 research/payg-sso-full/layout/language_switch.cfm create mode 100644 research/payg-sso-full/layout/page.cfm create mode 100644 research/payg-sso-full/layout/render_query.cfm create mode 100644 research/payg-sso-full/layout/xls.cfm create mode 100644 research/payg-sso-full/layout/xlshtm.cfm create mode 100644 research/payg-sso-full/layout/xml.cfm create mode 100644 research/payg-sso-full/lib/ac.cfm create mode 100644 research/payg-sso-full/lib/contenttype_icon.cfm create mode 100644 research/payg-sso-full/lib/controls/checkbox.cfm create mode 100644 research/payg-sso-full/lib/controls/column.cfm create mode 100644 research/payg-sso-full/lib/controls/column_head.cfm create mode 100644 research/payg-sso-full/lib/controls/combo.cfm create mode 100644 research/payg-sso-full/lib/controls/date.cfm create mode 100644 research/payg-sso-full/lib/controls/datetime.cfm create mode 100644 research/payg-sso-full/lib/controls/detail_buttons.cfm create mode 100644 research/payg-sso-full/lib/controls/grid_head.cfm create mode 100644 research/payg-sso-full/lib/controls/link_add.cfm create mode 100644 research/payg-sso-full/lib/controls/link_del.cfm create mode 100644 research/payg-sso-full/lib/controls/link_edit.cfm create mode 100644 research/payg-sso-full/lib/controls/link_view.cfm create mode 100644 research/payg-sso-full/lib/controls/link_view_edit.cfm create mode 100644 research/payg-sso-full/lib/controls/menu_item.cfm create mode 100644 research/payg-sso-full/lib/controls/nowbutton.cfm create mode 100644 research/payg-sso-full/lib/controls/order_arrows.cfm create mode 100644 research/payg-sso-full/lib/controls/paginator.cfm create mode 100644 research/payg-sso-full/lib/controls/table.cfm create mode 100644 research/payg-sso-full/lib/controls/td.cfm create mode 100644 research/payg-sso-full/lib/controls/text.cfm create mode 100644 research/payg-sso-full/lib/controls/th.cfm create mode 100644 research/payg-sso-full/lib/controls/time.cfm create mode 100644 research/payg-sso-full/lib/data/bean.cfm create mode 100644 research/payg-sso-full/lib/data/bean.cfm.bak create mode 100644 research/payg-sso-full/lib/data/bk/bean.cfm create mode 100644 research/payg-sso-full/lib/data/bk/bean.cfm.bak create mode 100644 research/payg-sso-full/lib/data/bk/field.cfm create mode 100644 research/payg-sso-full/lib/data/bk/field_set.cfm create mode 100644 research/payg-sso-full/lib/data/bk/param.cfm create mode 100644 research/payg-sso-full/lib/data/del.cfm create mode 100644 research/payg-sso-full/lib/data/del_condition.cfm create mode 100644 research/payg-sso-full/lib/data/dep_field.cfm create mode 100644 research/payg-sso-full/lib/data/dep_param.cfm create mode 100644 research/payg-sso-full/lib/data/dependency.cfm create mode 100644 research/payg-sso-full/lib/data/dependency_condition.cfm create mode 100644 research/payg-sso-full/lib/data/dependency_field.cfm create mode 100644 research/payg-sso-full/lib/data/dependency_from.cfm create mode 100644 research/payg-sso-full/lib/data/dependency_order_by.cfm create mode 100644 research/payg-sso-full/lib/data/field.cfm create mode 100644 research/payg-sso-full/lib/data/field_set.cfm create mode 100644 research/payg-sso-full/lib/data/param.cfm create mode 100644 research/payg-sso-full/lib/data/status.cfc create mode 100644 research/payg-sso-full/lib/data/submit_collection.cfm create mode 100644 research/payg-sso-full/lib/data/submit_param.cfm create mode 100644 research/payg-sso-full/lib/detail_page_info.cfc create mode 100644 research/payg-sso-full/lib/dispatch_detail.cfm create mode 100644 research/payg-sso-full/lib/encodingUtils.cfc create mode 100644 research/payg-sso-full/lib/filter_build.cf_ create mode 100644 research/payg-sso-full/lib/filter_build.cfm create mode 100644 research/payg-sso-full/lib/filter_page_info.cfc create mode 100644 research/payg-sso-full/lib/filter_rebuild.cfm create mode 100644 research/payg-sso-full/lib/filter_settings.cfm create mode 100644 research/payg-sso-full/lib/filterparam.cfm create mode 100644 research/payg-sso-full/lib/form_page_info.cfc create mode 100644 research/payg-sso-full/lib/generic_page_info.cfc create mode 100644 research/payg-sso-full/lib/init_settings.cfm create mode 100644 research/payg-sso-full/lib/jwt.cfc create mode 100644 research/payg-sso-full/lib/location.cfm create mode 100644 research/payg-sso-full/lib/ls_catch.cfm create mode 100644 research/payg-sso-full/lib/ls_page_info.cfc create mode 100644 research/payg-sso-full/lib/menu_item.cfm create mode 100644 research/payg-sso-full/lib/mimetype_icon.cfm create mode 100644 research/payg-sso-full/lib/oauth2.cfc create mode 100644 research/payg-sso-full/lib/order_build.cfm create mode 100644 research/payg-sso-full/lib/prepare_detail.cfm create mode 100644 research/payg-sso-full/lib/prepare_filter.cfm create mode 100644 research/payg-sso-full/lib/prepare_form.cfm create mode 100644 research/payg-sso-full/lib/prepare_ls.cfm create mode 100644 research/payg-sso-full/lib/rest_api_helper.cfc create mode 100644 research/payg-sso-full/lib/settings.cfm create mode 100644 research/payg-sso-full/lib/silent.cfm create mode 100644 research/payg-sso-full/lib/sortparam.cfm create mode 100644 research/payg-sso-full/lib/track.cfm create mode 100644 research/payg-sso-full/lib/upload.cfm create mode 100644 research/payg-sso-full/lib/utils/authStringBuilder.cfc create mode 100644 research/payg-sso-full/mod/conventions.txt create mode 100644 research/payg-sso-full/mod/crm_contract.cfm create mode 100644 research/payg-sso-full/mod/payg.cfm create mode 100644 research/payg-sso-full/mod/payg.cfm.1.bak create mode 100644 research/payg-sso-full/payg.cfm create mode 100644 research/payg-sso-full/style/web.css diff --git a/research/payg-sso-full/1.cfm b/research/payg-sso-full/1.cfm new file mode 100644 index 0000000..9f0caf1 --- /dev/null +++ b/research/payg-sso-full/1.cfm @@ -0,0 +1,11 @@ +
+test +
+ + + + + diff --git a/research/payg-sso-full/Application.cfc b/research/payg-sso-full/Application.cfc new file mode 100644 index 0000000..d3f85af --- /dev/null +++ b/research/payg-sso-full/Application.cfc @@ -0,0 +1,522 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ), + DE( "https://" ), + DE( "http://" ) + ) & + cgi.http_host & + reReplace( + getDirectoryFromPath( arguments.template ), "([^\\/]+[\\/]){#local.requestDepth#}$", + "", + "one" + ) + ) /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + var requestData = GetHttpRequestData(); + var headers = requestData.headers; + + if (structKeyExists(headers,"authorization")) { // аутентификация для клиента ЛК + var authorizationHeader = headers.authorization; + if (authorizationHeader.startsWith("Bearer ")) { + var bearerToken = Mid(authorizationHeader, 8); + writeDump(bearerToken); + //var token=toString(binaryDecode(bearerToken, "base64")); + //writeDump(token); + //jwt = new lib.jwt(this.client_secret); + //lock scope="application" type="readonly" timeout="1" { + // var token_data = (jwt.decode(token, application.idpCertificate,"RS256")); + //} + var result=""; + //try { + var iamService = new http(method = "GET", charset = "utf-8", url = #this.iam_url#, timeout="5"); + iamService.addParam(type = "HEADER", name = "Accept", value = "application/json"); + iamService.addParam(type = "HEADER", name = "Authorization", value = "#authorizationHeader#"); //passthrough + //writedump(this.iamServiceUrl);abort; + var resp = iamService.send(); + //if (resp.status_code NEQ 200) throw("IDP response not OK"); + //writedump(resp);abort; + var prefix = resp.getPrefix(); + if (prefix.status_code NEQ 200) { + //writedump(this.iamServiceUrl); + //writedump(resp); + var iamStatusCode = (isValid("integer", prefix.status_code)) ? val(prefix.status_code) : 500; + throw(message="IAM error", detail="URL: #this.iam_url# Status Code: #prefix.status_code#"); + //abort; + //throw("IDP response not OK"); + } + result = prefix.filecontent; + var idpUserData=deserializeJson(result); + //request.auth.wz=idpUserData.userInfo.ClientId;//GUID! + + + request.auth.login = idpUserData.userInfo.login; + //request.usrUid=idpUserData.userInfo.contactId;//userId; //GUID! + //writedump(idpUserData);abort; + //} catch (e) { + /*if (fileExists("#GetDirectoryFromPath(GetCurrentTemplatePath())#/etc/local-debug")) { //true for local debug without IDP, etc/* does not go to repository + var result='{"accounts":[{"login":"","type":"telegram"}],"avatar":["d2d2b7ac-50af-432b-b7c4-f7d6561e288a"],"company":"ООО «НУБЕС»","companyId":"8ec70ac0-546d-42a7-8cff-339c8fb51a23","contactId":"983967a3-58c2-4cdd-84a5-8b427ccfac82","email":"smishchuk@nubes.ru","externalUser":false,"fio":{"fullName":"Мищук Сергей ","name":"Сергей","secondName":"","surname":"Мищук"},"groupIds":["94bf5be7-52f4-5c13-87c3-513786934685","ab12b6b8-0265-4683-a5c2-5e1a74a55216","aff008c3-7443-50f6-86e1-ecff3cd3b04d","d6000da0-c9aa-55eb-9882-f118b432730b","d89a33dc-3177-5854-9580-f7f860a5ab7c","ddfe2555-9ef4-42cb-9a2b-7f24e61e7747","df12926f-ecb8-5479-857f-6d291464baad","fda5c295-230a-5025-9797-b8b4e99e08aa","2be9b4b6-94d1-59f9-a649-cab228d82169","64fe6f5c-a91b-5fea-a7ca-d9823701ebd4"],"integration":{"serviceId":""},"login":"smishchuk@nubes.ru","mobilePhone":[],"position":"","userId":"d72530e1-66a4-412f-a046-38153c4e5405"}';} + */ + //writedump(resp); + //return representationOf( {"exception"=e} ); + //rethrow(e); + //} + } + } else { + //точно мы так не словим дедлок ВПР + lock scope="session" type="readonly" timeout="3" { + if (structKeyExists(session, "auth")) { + request.auth = structCopy(session.auth); + } + } + if (structKeyExists(request, "auth") AND Now() < request.auth.exp) { + + if (dateDiff("s", request.auth.iat, Now()) > request.auth.refresh_expires_in/1.5 AND CGI.REQUEST_METHOD EQ "GET") { + // доля времени, после которой происходит рефреш, прибита гвоздями + // По всей видимости, рефреш будет ломать обращения POSТ + // В связи с чем предлагается дождаться GET + // Приклеивать query_string как-то не пришлось, браузер сам справляется + + // refresh + var idp = new lib.oauth2(this.client_id, this.client_secret, this.auth_endpoint, this.access_token_endpoint, this.redirect_uri); + var resp = idp.refreshAccessTokenRequest(request.auth.refresh_token); + + lock scope="application" type="readonly" timeout="1" { + idpCertificate = application.idpCertificate; + } + + var auth = parseIdpresponse(resp, idpCertificate, this.client_secret); //все эти сложности из-за опасений насчет многопоточности и блокировок + + lock scope="session" type="exclusive" timeout="1" { + session.auth = auth; + } + request.auth = auth; + writeDump(auth); + } + } else { + // сессии SSO нет + // или токен протух + request.auth_state = createGUID().toString(); + lock scope="session" type="exclusive" timeout="1" { + structDelete(session, "auth"); // зачистили сессию от данных SSO + session.auth_state = request.auth_state; + } + + var idp = new lib.oauth2(this.client_id, this.client_secret, this.auth_endpoint, this.access_token_endpoint, this.redirect_uri); + /* + часто появляется ошибка: после неудачного запроса к IDP + в адресной строке браузера остается все, с чем его редиректил IDP, + а повторный запрос с этим контентом уже не работает. Получаем 400 Bad Request - + может быть, KeyCloak так защищается от циклических редиректов + Не очень понятно, как предотвратить повторный запрос (можно, конечно, использовать сессию, но странно) + */ + //writeOutput(getTickCount()-request.startTickCount); + if(structKeyExists(url, "code")) { //обрабатываем редирект от IDP *** наличие поля code в URL введет нас в заблуждение, + + try { + //writeOutput("idp.makeAccessTokenRequest"); + //writeOutput(getTickCount()-request.startTickCount); + var resp = idp.makeAccessTokenRequest(url.code); + + lock scope="application" type="readonly" timeout="1" { + idpCertificate = application.idpCertificate; + } + + var auth = parseIdpresponse(resp, idpCertificate, this.client_secret); //все эти сложности из-за опасений насчет многопоточности и блокировок + + lock scope="session" type="exclusive" timeout="1" { + session.auth = auth; + } + //request.auth = auth; + location(this.redirect_uri, false); + } catch (e) {echo('
****************** #e.message# : #e.detail# **************');} + + } else { //отправляем браузер к IDP + var strURL =idp.buildRedirectToAuthURL({"scope":'openid profile email',"state":request.auth_state,"allow_signup":false}); + echo('self-made Auth link (idp) #strURL#

'); + location(strUrl,false); + } + + } + + } + + //request.logout_url = ""; + if (structKeyExists(request, "auth") AND structKeyExists(request.auth, "id_token")) { + request.logout_url = "#this.logout_endpoint#?id_token_hint=#request.auth.id_token#&post_logout_redirect_uri=#this.redirect_uri#?logout"; + // внимание, здесь подразумевается, что redirect_uri не содержит query_string + // после возвращения от IDP нам нужно будет зачистить сессию SSO, сделаем это по слову logout + } + + request.auth.wz='WZ01348'; //******************* +
+ + + + + + + + + + + ---> + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + select value as stand from config + where name='STAND' + + + + + + + + + + + + + + + + + + + select 1; + + + + + + + + + + + + + + + + + + + + select 2; + + + + + + + + + + + + + + + + + + + //https://keycloak.nubes.ru/admin + //https://keycloak.nubes.ru/realms/SSH_CA/account //smishchuk@mgmt.nubes.ru + //https://stackoverflow.com/questions/28658735/what-are-keycloaks-oauth2-openid-connect-endpoints + //http://https://keycloak.nubes.ru/realms/SSH_CA/.well-known/openid-configuration + + //https://keycloak.nubes.ru/realms/cloud/.well-known/openid-configuration тут ссылка + //https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/certs тут серт + //только надо его обрамить -----BEGIN CERTIFICATE----- + private function getIdpCertificate(certUrl) { + + var httpService = new http(); + httpService.setMethod( "get" ); + httpService.setCharset( "utf-8" ); + httpService.setUrl(arguments.certUrl); + + var result = httpService.send().getPrefix(); + var status_code = result.ResponseHeader['Status_Code']; + + if ('200' == status_code) { + var content = deserializeJson(result.FileContent); + //мы подразумеваем структуру конкретно KeyCloak + var key = ""; + for (key in content.keys) { + if ("RSA" == key.kty AND "sig" == key.use) { + return "-----BEGIN CERTIFICATE-----" & key.x5c[1] & "-----END CERTIFICATE-----"; + } + } + throw(message="RSA cetificate not found"); + } else { + throw (message="Cannot obtain IDP certificate, request failed", detail="Status_Code #status_code#"); + } + } + + private struct function parseIdpResponse(struct resp, string certificate, string jwt_secret) { + + var auth = structNew("linked"); + var data = deserializeJson(arguments.resp.content); + var jwt = new lib.jwt(arguments.jwt_secret); + + auth.expires_in = data.expires_in; + auth.refresh_expires_in = data.refresh_expires_in; + auth.access_token = data.access_token; + auth.refresh_token = data.refresh_token; + auth.id_token = data.id_token; + auth.token_type = data.token_type; + + //idp_response_content = structCopy(data); //for debug + var token_data = (jwt.decode(data.access_token, arguments.certificate,"RS256")); + + auth.session_state = token_data.session_state; + auth.sid = token_data.sid; + auth.auth_time = token_data.auth_time; + auth.exp = token_data.exp; + auth.iat = token_data.iat; + + auth.login = token_data.preferred_username; + auth.wz = token_data.ClientID; + auth.fullname = token_data.name; + auth.groups = token_data.groups; + //auth.token_data = structCopy(token_data); //for debug + + return (auth); + } + + + + + + + + + + + + +
\ No newline at end of file diff --git a/research/payg-sso-full/etc/2do.txt b/research/payg-sso-full/etc/2do.txt new file mode 100644 index 0000000..d422f00 --- /dev/null +++ b/research/payg-sso-full/etc/2do.txt @@ -0,0 +1,6 @@ +корректный период +другие WZ +? full join +детализация - для S3 это бакеты + + diff --git a/research/payg-sso-full/etc/db/billing_schema.sql b/research/payg-sso-full/etc/db/billing_schema.sql new file mode 100644 index 0000000..caaf1d3 --- /dev/null +++ b/research/payg-sso-full/etc/db/billing_schema.sql @@ -0,0 +1,595 @@ +база rpt сделана из базы billing (название изменено, чтобы избежать путаницы) +-- удалены последовательности, переназначены владельцы и права +-- удалены внешние ключи + +-- создать роль dbo (владелец), без connect +-- создать пользователя nifi, с правом логина +-- создать пользователя appserver, с правом логина +-- дать права пользователю nifi на схемы и таблицы +-- дать права пользователю appserver на схемы и таблицы на чтение + +SET ROLE postgres; + +CREATE SCHEMA IF NOT EXISTS s3billing; +CREATE SCHEMA IF NOT EXISTS ngcloud_ru; + +ALTER SCHEMA s3billing OWNER TO dbo; +ALTER SCHEMA ngcloud_ru OWNER TO dbo; +ALTER DATABASE rpt SET search_path TO s3billing, ngcloud_ru; + +ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres GRANT ALL ON TABLES TO nifi; +ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres GRANT SELECT ON TABLES TO appserver; + +SET ROLE dbo; + +GRANT USAGE ON SCHEMA s3billing TO appserver,nifi; +GRANT USAGE ON SCHEMA ngcloud_ru TO appserver,nifi; + +GRANT ALL ON ALL TABLES IN SCHEMA s3billing TO nifi; +GRANT SELECT ON ALL TABLES IN SCHEMA s3billing TO appserver; + +GRANT ALL ON ALL TABLES IN SCHEMA ngcloud_ru TO nifi; +GRANT SELECT ON ALL TABLES IN SCHEMA ngcloud_ru TO appserver; + +--GRANT ALL ON ALL SEQUENCES IN SCHEMA s3billing TO appserver,nifi; +--GRANT ALL ON ALL SEQUENCES IN SCHEMA ngcloud_ru TO appserver,nifi; + + +--ALTER DEFAULT PRIVILEGES FOR ROLE dbo GRANT ALL ON SEQUENCES TO appserver,nifi; + +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 16.0 +-- Dumped by pg_dump version 16.4 + +-- Started on 2025-09-15 09:50:58 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- TOC entry 230 (class 1259 OID 2160668) +-- Name: bucket_info; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +DROP TABLE IF EXISTS s3billing.bucket_info; +CREATE TABLE s3billing.bucket_info ( + id integer NOT NULL, + bucket_id character varying(255) NOT NULL, + name character varying(255) NOT NULL, + marker character varying(255) NOT NULL, + placement_id bigint DEFAULT 0 NOT NULL +); + + + + +-- +-- TOC entry 226 (class 1259 OID 2160642) +-- Name: bucket_stat; Type: TABLE; Schema: s3billing; Owner: s3billing +-- +DROP TABLE IF EXISTS s3billing.bucket_stat; +CREATE TABLE s3billing.bucket_stat ( + bucket_id bigint, + num_shards bigint NOT NULL, + tenant character varying(255) DEFAULT NULL::character varying, + zone_group bigint NOT NULL, + placement_id bigint NOT NULL, + explicit_placement_data_pool character varying(255) DEFAULT NULL::character varying, + explicit_placement_data_extra_pool character varying(255) DEFAULT NULL::character varying, + explicit_placement_index_pool character varying(255) DEFAULT NULL::character varying, + index_type_id bigint NOT NULL, + versioned boolean DEFAULT false, + versioning_enabled boolean DEFAULT false, + object_lock_enabled boolean DEFAULT false, + mfa_enabled boolean DEFAULT false, + owner character varying(255) NOT NULL, + bucket_quota_enabled boolean DEFAULT false, + bucket_quota_check_on_raw boolean DEFAULT false, + bucket_quota_max_size bigint NOT NULL, + bucket_quota_max_size_kb bigint NOT NULL, + bucket_quota_max_objects bigint NOT NULL, + usage_rgw_main_size bigint NOT NULL, + usage_rgw_main_size_actual bigint NOT NULL, + usage_rgw_main_size_utilized bigint NOT NULL, + usage_rgw_main_size_kb bigint NOT NULL, + usage_rgw_main_size_kb_actual bigint NOT NULL, + usage_rgw_main_size_kb_utilized bigint NOT NULL, + usage_rgw_main_num_objects bigint NOT NULL, + usage_rgw_multimeta_size bigint, + usage_rgw_multimeta_size_actual bigint, + usage_rgw_multimeta_size_utilized bigint, + usage_rgw_multimeta_size_kb bigint, + usage_rgw_multimeta_size_kb_actual bigint, + usage_rgw_multimeta_size_kb_utilized bigint, + usage_rgw_multimeta_num_objects bigint, + creation_time timestamp without time zone NOT NULL, + mtime timestamp without time zone NOT NULL, + timestamp_addition timestamp without time zone DEFAULT date_trunc('hour'::text, CURRENT_TIMESTAMP) +); + +-- +-- TOC entry 245 (class 1259 OID 2160763) +-- Name: category; Type: TABLE; Schema: s3billing; Owner: s3billing +-- +DROP TABLE IF EXISTS s3billing.category; +CREATE TABLE s3billing.category ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + +-- +-- TOC entry 225 (class 1259 OID 2160635) +-- Name: goose_db_version; Type: TABLE; Schema: s3billing; Owner: s3billing +-- +DROP TABLE IF EXISTS s3billing.goose_db_version; +CREATE TABLE s3billing.goose_db_version ( + id integer NOT NULL, + version_id bigint NOT NULL, + is_applied boolean NOT NULL, + tstamp timestamp without time zone DEFAULT now() NOT NULL +); + + +-- +-- TOC entry 234 (class 1259 OID 2160684) +-- Name: index_type; Type: TABLE; Schema: s3billing; Owner: s3billing +-- +DROP TABLE IF EXISTS index_type; +CREATE TABLE s3billing.index_type ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + + +-- +-- TOC entry 232 (class 1259 OID 2160677) +-- Name: placement; Type: TABLE; Schema: s3billing; Owner: s3billing +-- +DROP TABLE IF EXISTS s3billing.placement; +CREATE TABLE s3billing.placement ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + + + +-- +-- TOC entry 239 (class 1259 OID 2160705) +-- Name: usage_bucket_by_user; Type: TABLE; Schema: s3billing; Owner: s3billing +-- +DROP TABLE IF EXISTS s3billing.usage_bucket_by_user; +CREATE TABLE s3billing.usage_bucket_by_user ( + bucketid bigint, + "time" timestamp without time zone NOT NULL, + bytes_sent bigint NOT NULL, + bytes_received bigint NOT NULL, + ops bigint NOT NULL, + successful_ops bigint NOT NULL, + date_start timestamp without time zone NOT NULL, + date_end timestamp without time zone NOT NULL, + user_id bigint NOT NULL, + category_id bigint NOT NULL +); + + +-- +-- TOC entry 238 (class 1259 OID 2160698) +-- Name: usage_stat_summary; Type: TABLE; Schema: s3billing; Owner: s3billing +-- +DROP TABLE IF EXISTS s3billing.usage_stat_summary; +CREATE TABLE s3billing.usage_stat_summary ( + id integer NOT NULL, + userid character varying(255) NOT NULL, + category character varying(255) NOT NULL, + bytes_sent bigint NOT NULL, + bytes_received bigint NOT NULL, + ops bigint NOT NULL, + successful_ops bigint NOT NULL, + date_start timestamp without time zone NOT NULL, + date_end timestamp without time zone NOT NULL +); + + +-- +-- TOC entry 236 (class 1259 OID 2160691) +-- Name: usage_stat_total; Type: TABLE; Schema: s3billing; Owner: s3billing +-- +DROP TABLE IF EXISTS s3billing.usage_stat_total; +CREATE TABLE s3billing.usage_stat_total ( + id integer NOT NULL, + userid character varying(255) NOT NULL, + bytes_sent bigint NOT NULL, + bytes_received bigint NOT NULL, + ops bigint NOT NULL, + successful_ops bigint NOT NULL, + date_start timestamp without time zone NOT NULL, + date_end timestamp without time zone NOT NULL +); + +-- +-- TOC entry 243 (class 1259 OID 2160751) +-- Name: user_info; Type: TABLE; Schema: s3billing; Owner: s3billing +-- +DROP TABLE IF EXISTS s3billing.user_info; +CREATE TABLE s3billing.user_info ( + id integer NOT NULL, + name character varying(255) NOT NULL, + owner character varying(255) NOT NULL +); + + +-- +-- TOC entry 241 (class 1259 OID 2160712) +-- Name: user_quota_bucket; Type: TABLE; Schema: s3billing; Owner: s3billing +-- +DROP TABLE IF EXISTS s3billing.user_quota_bucket; +CREATE TABLE s3billing.user_quota_bucket ( + id integer NOT NULL, + userid character varying(255) NOT NULL, + enabled boolean DEFAULT false, + check_on_raw boolean DEFAULT false, + max_size bigint NOT NULL, + max_size_kb bigint NOT NULL, + max_objects bigint NOT NULL +); + + +-- +-- TOC entry 228 (class 1259 OID 2160661) +-- Name: zone_group; Type: TABLE; Schema: s3billing; Owner: s3billing +-- +DROP TABLE IF EXISTS s3billing.zone_group; +CREATE TABLE s3billing.zone_group ( + id integer NOT NULL, + name uuid NOT NULL +); + +-- +-- TOC entry 3278 (class 2606 OID 2160675) +-- Name: bucket_info bucket_info_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.bucket_info + ADD CONSTRAINT bucket_info_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3273 (class 2606 OID 2476484) +-- Name: bucket_stat bucket_stat_unique; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +--ALTER TABLE ONLY s3billing.bucket_stat +-- ADD CONSTRAINT bucket_stat_unique UNIQUE (bucket_id, placement_id, timestamp_addition); + +ALTER TABLE ONLY s3billing.bucket_stat + ADD CONSTRAINT bucket_stat_pkey PRIMARY KEY (bucket_id, placement_id, timestamp_addition); + + +-- +-- TOC entry 3298 (class 2606 OID 2160768) +-- Name: category category_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.category + ADD CONSTRAINT category_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3270 (class 2606 OID 2160640) +-- Name: goose_db_version goose_db_version_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.goose_db_version + ADD CONSTRAINT goose_db_version_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3284 (class 2606 OID 2160689) +-- Name: index_type index_type_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.index_type + ADD CONSTRAINT index_type_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3282 (class 2606 OID 2160682) +-- Name: placement placement_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.placement + ADD CONSTRAINT placement_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3290 (class 2606 OID 2476705) +-- Name: usage_bucket_by_user usage_bucket_by_user_unique; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +--ALTER TABLE ONLY s3billing.usage_bucket_by_user +-- ADD CONSTRAINT usage_bucket_by_user_unique UNIQUE (bucketid, date_start, date_end, user_id, category_id); +ALTER TABLE ONLY s3billing.usage_bucket_by_user + ADD CONSTRAINT usage_bucket_by_user_pkey PRIMARY KEY (bucketid, date_start, date_end, user_id, category_id); + + +-- +-- TOC entry 3288 (class 2606 OID 2160703) +-- Name: usage_stat_summary usage_stat_summary_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_stat_summary + ADD CONSTRAINT usage_stat_summary_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3286 (class 2606 OID 2160696) +-- Name: usage_stat_total usage_stat_total_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_stat_total + ADD CONSTRAINT usage_stat_total_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3295 (class 2606 OID 2160758) +-- Name: user_info user_info_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.user_info + ADD CONSTRAINT user_info_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3292 (class 2606 OID 2160719) +-- Name: user_quota_bucket user_quota_bucket_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.user_quota_bucket + ADD CONSTRAINT user_quota_bucket_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3275 (class 2606 OID 2160666) +-- Name: zone_group zone_group_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.zone_group + ADD CONSTRAINT zone_group_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3276 (class 1259 OID 2474077) +-- Name: bucket_info_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX bucket_info_name_idx ON s3billing.bucket_info USING btree (name); + + +-- +-- TOC entry 3279 (class 1259 OID 2474078) +-- Name: bucket_info_placement_id_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX bucket_info_placement_id_idx ON s3billing.bucket_info USING btree (placement_id); + + +-- +-- TOC entry 3271 (class 1259 OID 2474094) +-- Name: bucket_stat_owner_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX bucket_stat_owner_idx ON s3billing.bucket_stat USING btree (owner); + + +-- +-- TOC entry 3296 (class 1259 OID 2474445) +-- Name: category_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE UNIQUE INDEX category_name_idx ON s3billing.category USING btree (name); + + +-- +-- TOC entry 3280 (class 1259 OID 2474468) +-- Name: placement_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE UNIQUE INDEX placement_name_idx ON s3billing.placement USING btree (name); + + +-- +-- TOC entry 3293 (class 1259 OID 2474438) +-- Name: user_info_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX user_info_name_idx ON s3billing.user_info USING btree (name); + + + +-- Completed on 2025-09-15 09:50:59 + +-- +-- PostgreSQL database dump complete +-- + +------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------- + +DROP TABLE IF EXISTS ngcloud_ru.capacity_resource; +CREATE TABLE ngcloud_ru.capacity_resource ( + vdc_id uuid NOT NULL, + "timestamp" timestamp with time zone NOT NULL, + cpu_allocated integer NOT NULL, + cpu_limit integer NOT NULL, + cpu_reserved integer NOT NULL, + cpu_used integer NOT NULL, + cpu_speed integer NOT NULL, + mem_allocated integer NOT NULL, + mem_limit integer NOT NULL, + mem_reserved integer NOT NULL, + mem_used integer NOT NULL +); + +-- +-- TOC entry 223 (class 1259 OID 1893993) +-- Name: capacity_storage; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- +DROP TABLE IF EXISTS ngcloud_ru.capacity_storage; +CREATE TABLE ngcloud_ru.capacity_storage ( + vdc_id uuid NOT NULL, + storage_profile_types_id integer NOT NULL, + "timestamp" timestamp with time zone NOT NULL, + id uuid NOT NULL, + "limit" integer NOT NULL, + used integer NOT NULL +); + +-- +-- TOC entry 220 (class 1259 OID 1893965) +-- Name: storage_profile_types; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- +DROP TABLE IF EXISTS ngcloud_ru.storage_profile_types; +CREATE TABLE ngcloud_ru.storage_profile_types ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + +-- +-- TOC entry 218 (class 1259 OID 1893959) +-- Name: tenant; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- +DROP TABLE IF EXISTS ngcloud_ru.tenant; +CREATE TABLE ngcloud_ru.tenant ( + id uuid NOT NULL, + name character varying(255) NOT NULL, + wzcode bigint +); + + +-- +-- TOC entry 221 (class 1259 OID 1893973) +-- Name: vdc; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- +DROP TABLE IF EXISTS ngcloud_ru.vdc; +CREATE TABLE ngcloud_ru.vdc ( + id uuid NOT NULL, + tenant_id uuid NOT NULL, + name character varying(255) NOT NULL +); + + + + + +-- +-- TOC entry 3255 (class 2606 OID 1893987) +-- Name: capacity_resource capacity_resource_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_resource + ADD CONSTRAINT capacity_resource_pkey PRIMARY KEY (vdc_id, "timestamp"); + + +-- +-- TOC entry 3257 (class 2606 OID 1893997) +-- Name: capacity_storage capacity_storage_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_storage + ADD CONSTRAINT capacity_storage_pkey PRIMARY KEY (vdc_id, id, "timestamp"); + + +-- +-- TOC entry 3249 (class 2606 OID 1893972) +-- Name: storage_profile_types storage_profile_types_name_key; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.storage_profile_types + ADD CONSTRAINT storage_profile_types_name_key UNIQUE (name); + + +-- +-- TOC entry 3251 (class 2606 OID 1893970) +-- Name: storage_profile_types storage_profile_types_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.storage_profile_types + ADD CONSTRAINT storage_profile_types_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3247 (class 2606 OID 1893963) +-- Name: tenant tenant_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.tenant + ADD CONSTRAINT tenant_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3253 (class 2606 OID 1893977) +-- Name: vdc vdc_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.vdc + ADD CONSTRAINT vdc_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3259 (class 2606 OID 1893988) +-- Name: capacity_resource capacity_resource_vdc_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +--ALTER TABLE ONLY ngcloud_ru.capacity_resource +-- ADD CONSTRAINT capacity_resource_vdc_id_fkey FOREIGN KEY (vdc_id) REFERENCES ngcloud_ru.vdc(id) ON DELETE CASCADE; + + +-- +-- TOC entry 3260 (class 2606 OID 1894003) +-- Name: capacity_storage capacity_storage_storage_profile_types_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +--ALTER TABLE ONLY ngcloud_ru.capacity_storage +-- ADD CONSTRAINT capacity_storage_storage_profile_types_id_fkey FOREIGN KEY (storage_profile_types_id) REFERENCES ngcloud_ru.storage_profile_types(id); + + +-- +-- TOC entry 3261 (class 2606 OID 1893998) +-- Name: capacity_storage capacity_storage_vdc_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +--ALTER TABLE ONLY ngcloud_ru.capacity_storage +-- ADD CONSTRAINT capacity_storage_vdc_id_fkey FOREIGN KEY (vdc_id) REFERENCES ngcloud_ru.vdc(id) ON DELETE CASCADE; + + +-- +-- TOC entry 3258 (class 2606 OID 1893978) +-- Name: vdc vdc_tenant_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +--ALTER TABLE ONLY ngcloud_ru.vdc +-- ADD CONSTRAINT vdc_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES ngcloud_ru.tenant(id); + + +-- Completed on 2025-09-15 09:53:18 + +-- +-- PostgreSQL database dump complete +-- + diff --git a/research/payg-sso-full/etc/db/billing_schema2.sql b/research/payg-sso-full/etc/db/billing_schema2.sql new file mode 100644 index 0000000..71bef00 --- /dev/null +++ b/research/payg-sso-full/etc/db/billing_schema2.sql @@ -0,0 +1,1766 @@ +-- +-- PostgreSQL database dump +-- + +\restrict M18FnaokuZFKQZjWu9az6dzOO6o2cSlpJgAocs2PXfRbmzHVcXEXaiZZcaOPZko + +-- Dumped from database version 16.0 +-- Dumped by pg_dump version 17.6 + +-- Started on 2025-10-24 14:30:46 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET transaction_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- TOC entry 6 (class 2615 OID 1891106) +-- Name: def; Type: SCHEMA; Schema: -; Owner: dbo +-- + +CREATE SCHEMA def; + + +ALTER SCHEMA def OWNER TO dbo; + +-- +-- TOC entry 7 (class 2615 OID 1891160) +-- Name: ngcloud_ru; Type: SCHEMA; Schema: -; Owner: vc_billing +-- + +CREATE SCHEMA ngcloud_ru; + + +ALTER SCHEMA ngcloud_ru OWNER TO vc_billing; + +-- +-- TOC entry 8 (class 2615 OID 2160630) +-- Name: s3billing; Type: SCHEMA; Schema: -; Owner: s3billing +-- + +CREATE SCHEMA s3billing; + + +ALTER SCHEMA s3billing OWNER TO s3billing; + +-- +-- TOC entry 246 (class 1255 OID 2426393) +-- Name: billing(timestamp with time zone, timestamp with time zone, character varying); Type: FUNCTION; Schema: s3billing; Owner: dsorokin +-- + +CREATE FUNCTION s3billing.billing(_ds timestamp with time zone, _df timestamp with time zone, _user character varying) RETURNS TABLE(bucket_name character varying, placement character varying, size numeric, put numeric, get numeric, bytes_sent numeric) + LANGUAGE plpgsql + AS $$ +BEGIN +SELECT + s3billing.bucket_info.name AS bucket_name + ,s3billing.placement.name AS placement + ,coalesce(round(sum(usage_rgw_main_size_actual)/(24*(SELECT DATE_PART('day', (_ds-_df))))),0) AS size + ,coalesce(s2.get, 0) AS get + ,coalesce(s2.put, 0) AS put + ,coalesce(s2.bytes_sent, 0) as bytes_sent +FROM s3billing.bucket_stat +INNER JOIN s3billing.placement ON s3billing.bucket_stat.placement_id=s3billing.placement.id +INNER JOIN s3billing.bucket_info ON s3billing.bucket_stat.bucket_id=s3billing.bucket_info.id +LEFT JOIN ( + SELECT + s1.bucket_id AS bucket_id + ,s1.bucket_name AS bucket_name + ,s1.placement AS placement + ,coalesce(sum(s1.get) ,0) AS get + ,coalesce(sum(s1.put) ,0) AS put + ,coalesce(sum(s1.bytes_sent), 0) AS bytes_sent + FROM ( + SELECT + s3billing.bucket_info.id AS bucket_id + ,s3billing.bucket_info.name AS bucket_name + ,s3billing.placement.name AS placement + ,(CASE + WHEN ( s3billing.category.name LIKE 'get%' + OR s3billing.category.name LIKE 'head%' + OR s3billing.category.name LIKE 'options%' + ) THEN coalesce(sum(ops), 0) + END) AS get + ,(CASE + WHEN ( s3billing.category.name LIKE 'put%' + OR s3billing.category.name LIKE 'post%' + OR s3billing.category.name LIKE 'patch%' + OR s3billing.category.name LIKE 'list%' + ) THEN coalesce(sum(ops), 0) + END) AS put + ,coalesce(sum(usage_bucket_by_user.bytes_sent), 0) AS bytes_sent + FROM + s3billing.usage_bucket_by_user + INNER JOIN s3billing.bucket_info ON s3billing.usage_bucket_by_user.bucketid = s3billing.bucket_info.id + INNER JOIN s3billing.placement ON s3billing.bucket_info.placement_id = s3billing.placement.id + INNER JOIN s3billing.user_info ON s3billing.usage_bucket_by_user.user_id = s3billing.user_info.id + INNER JOIN s3billing.category ON s3billing.usage_bucket_by_user.category_id = s3billing.category.id + + WHERE + s3billing.user_info.name=_user + AND s3billing.usage_bucket_by_user.time >= _ds + AND s3billing.usage_bucket_by_user.time < _df + GROUP BY + s3billing.bucket_info.name + ,s3billing.placement.name + ,s3billing.category.name + ,s3billing.bucket_info.id + ) AS s1 + GROUP BY + s1.bucket_name + ,s1.bucket_id + ,s1.placement + ORDER BY + s1.placement + ,s1.bucket_name +) AS s2 ON s2.bucket_id = s3billing.bucket_stat.bucket_id +WHERE owner=_user + AND timestamp_addition >= _ds + AND timestamp_addition < _df +GROUP BY + s3billing.bucket_info.name + ,s3billing.placement.name + ,s3billing.bucket_stat.bucket_id + ,s2.get + ,s2.put + ,s2.bytes_sent +ORDER BY + s3billing.placement.name +,s3billing.bucket_info.name +; +END +$$; + + +ALTER FUNCTION s3billing.billing(_ds timestamp with time zone, _df timestamp with time zone, _user character varying) OWNER TO dsorokin; + +-- +-- TOC entry 260 (class 1255 OID 2434574) +-- Name: billing_per_user(character varying, character varying, character varying); Type: FUNCTION; Schema: s3billing; Owner: dsorokin +-- + +CREATE FUNCTION s3billing.billing_per_user(_ds character varying, _df character varying, _user character varying) RETURNS TABLE(bucket_name character varying, placement character varying, size numeric, get numeric, put numeric, bytes_sent numeric) + LANGUAGE plpgsql + AS $$ +BEGIN +RETURN QUERY + +SELECT + s3billing.bucket_info.name AS bucket_name + ,s3billing.placement.name AS placement + ,coalesce(round(sum(usage_rgw_main_size_actual)/ + (SELECT (DATE_PART('day', + ((TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS')) + -TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS')) + )*24+ + DATE_PART('hour', + ((TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS')) + -TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS')) + ))) + + )::numeric,0) AS size + ,coalesce(s2.get, 0) AS get + ,coalesce(s2.put, 0) AS put + ,coalesce(s2.bytes_sent, 0) as bytes_sent +FROM s3billing.bucket_stat +INNER JOIN s3billing.placement ON s3billing.bucket_stat.placement_id=s3billing.placement.id +INNER JOIN s3billing.bucket_info ON s3billing.bucket_stat.bucket_id=s3billing.bucket_info.id +LEFT JOIN ( + SELECT + s1.bucket_id AS bucket_id + ,s1.bucket_name AS bucket_name + ,s1.placement AS placement + ,coalesce(sum(s1.get) ,0) AS get + ,coalesce(sum(s1.put) ,0) AS put + ,coalesce(sum(s1.bytes_sent), 0) AS bytes_sent + FROM ( + SELECT + s3billing.bucket_info.id AS bucket_id + ,s3billing.bucket_info.name AS bucket_name + ,s3billing.placement.name AS placement + ,(CASE + WHEN ( s3billing.category.name LIKE 'get%' + OR s3billing.category.name LIKE 'head%' + OR s3billing.category.name LIKE 'options%' + ) THEN coalesce(sum(ops), 0) + END) AS get + ,(CASE + WHEN ( s3billing.category.name LIKE 'put%' + OR s3billing.category.name LIKE 'post%' + OR s3billing.category.name LIKE 'patch%' + OR s3billing.category.name LIKE 'list%' + ) THEN coalesce(sum(ops), 0) + END) AS put + ,coalesce(sum(usage_bucket_by_user.bytes_sent), 0) AS bytes_sent + + FROM + s3billing.usage_bucket_by_user + INNER JOIN s3billing.bucket_info ON s3billing.usage_bucket_by_user.bucketid = s3billing.bucket_info.id + INNER JOIN s3billing.placement ON s3billing.bucket_info.placement_id = s3billing.placement.id + INNER JOIN s3billing.user_info ON s3billing.usage_bucket_by_user.user_id = s3billing.user_info.id + INNER JOIN s3billing.category ON s3billing.usage_bucket_by_user.category_id = s3billing.category.id + + WHERE + s3billing.user_info.name=_user + AND s3billing.usage_bucket_by_user.time >=TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS') + AND s3billing.usage_bucket_by_user.time < TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS') + GROUP BY + s3billing.bucket_info.name + ,s3billing.placement.name + ,s3billing.category.name + ,s3billing.bucket_info.id + ) AS s1 + + GROUP BY + s1.bucket_name + ,s1.bucket_id + ,s1.placement + + ORDER BY + s1.placement + ,s1.bucket_name + +) AS s2 ON s2.bucket_id = s3billing.bucket_stat.bucket_id +WHERE owner=_user + AND timestamp_addition >= TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS') + AND timestamp_addition < TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS') +GROUP BY + s3billing.bucket_info.name + ,s3billing.placement.name + ,s3billing.bucket_stat.bucket_id + ,s2.get + ,s2.put + ,s2.bytes_sent +ORDER BY + s3billing.placement.name +,s3billing.bucket_info.name +; +END; +$$; + + +ALTER FUNCTION s3billing.billing_per_user(_ds character varying, _df character varying, _user character varying) OWNER TO dsorokin; + +-- +-- TOC entry 261 (class 1255 OID 2435525) +-- Name: billing_per_user_fix_pl(character varying, character varying, character varying); Type: FUNCTION; Schema: s3billing; Owner: dsorokin +-- + +CREATE FUNCTION s3billing.billing_per_user_fix_pl(_ds character varying, _df character varying, _user character varying) RETURNS TABLE(bucket_name character varying, placement character varying, size numeric, get numeric, put numeric, bytes_sent numeric) + LANGUAGE plpgsql + AS $$ +BEGIN +RETURN QUERY + +SELECT + s3billing.bucket_info.name AS bucket_name, + (case + when ( s3billing.placement.name = 'default-placement') then 'HOT' + WHEN ( not s3billing.placement.name = 'default-placement' ) THEN s3billing.placement.name + end + ) as placement, + coalesce(round(sum(usage_rgw_main_size_actual)/ + (SELECT (DATE_PART('day', + ((TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS')) + -TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS')) + )*24+ + DATE_PART('hour', + ((TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS')) + -TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS')) + ))) + + )::numeric,0) AS size + ,coalesce(s2.get, 0) AS get + ,coalesce(s2.put, 0) AS put + ,coalesce(s2.bytes_sent, 0) as bytes_sent +FROM s3billing.bucket_stat +INNER JOIN s3billing.placement ON s3billing.bucket_stat.placement_id=s3billing.placement.id +INNER JOIN s3billing.bucket_info ON s3billing.bucket_stat.bucket_id=s3billing.bucket_info.id +LEFT JOIN ( + SELECT + s1.bucket_id AS bucket_id + ,s1.bucket_name AS bucket_name, + (case + when ( s1.placement = 'default-placement') then 'HOT' + WHEN ( not s1.placement = 'default-placement' ) THEN s1.placement + end + ) as placement + ,coalesce(sum(s1.get) ,0) AS get + ,coalesce(sum(s1.put) ,0) AS put + ,coalesce(sum(s1.bytes_sent), 0) AS bytes_sent + FROM ( + SELECT + s3billing.bucket_info.id AS bucket_id + ,s3billing.bucket_info.name AS bucket_name + ,(case + when ( s3billing.placement.name = 'default-placement') then 'HOT' + WHEN ( not s3billing.placement.name = 'default-placement' ) THEN s3billing.placement.name + end + ) as placement + ,(CASE + WHEN ( s3billing.category.name LIKE 'get%' + OR s3billing.category.name LIKE 'head%' + OR s3billing.category.name LIKE 'options%' + ) THEN coalesce(sum(ops), 0) + END) AS get + ,(CASE + WHEN ( s3billing.category.name LIKE 'put%' + OR s3billing.category.name LIKE 'post%' + OR s3billing.category.name LIKE 'patch%' + OR s3billing.category.name LIKE 'list%' + ) THEN coalesce(sum(ops), 0) + END) AS put + ,coalesce(sum(usage_bucket_by_user.bytes_sent), 0) AS bytes_sent + + FROM + s3billing.usage_bucket_by_user + INNER JOIN s3billing.bucket_info ON s3billing.usage_bucket_by_user.bucketid = s3billing.bucket_info.id + INNER JOIN s3billing.placement ON s3billing.bucket_info.placement_id = s3billing.placement.id + INNER JOIN s3billing.user_info ON s3billing.usage_bucket_by_user.user_id = s3billing.user_info.id + INNER JOIN s3billing.category ON s3billing.usage_bucket_by_user.category_id = s3billing.category.id + + WHERE + s3billing.user_info.name=_user + AND s3billing.usage_bucket_by_user.time >=TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS') + AND s3billing.usage_bucket_by_user.time < TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS') + GROUP BY + s3billing.bucket_info.name + ,s3billing.placement.name + ,s3billing.category.name + ,s3billing.bucket_info.id + ) AS s1 + + GROUP BY + s1.bucket_name + ,s1.bucket_id + ,s1.placement + + ORDER BY + s1.placement + ,s1.bucket_name + +) AS s2 ON s2.bucket_id = s3billing.bucket_stat.bucket_id +WHERE owner=_user + AND timestamp_addition >= TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS') + AND timestamp_addition < TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS') +GROUP BY + s3billing.bucket_info.name + ,s3billing.placement.name + ,s3billing.bucket_stat.bucket_id + ,s2.get + ,s2.put + ,s2.bytes_sent +ORDER BY + s3billing.placement.name +,s3billing.bucket_info.name +; +END; +$$; + + +ALTER FUNCTION s3billing.billing_per_user_fix_pl(_ds character varying, _df character varying, _user character varying) OWNER TO dsorokin; + +-- +-- TOC entry 263 (class 1255 OID 2437728) +-- Name: billing_per_user_fix_pl_sv(character varying, character varying, character varying); Type: FUNCTION; Schema: s3billing; Owner: postgres +-- + +CREATE FUNCTION s3billing.billing_per_user_fix_pl_sv(ds character varying, df character varying, _user character varying) RETURNS TABLE(bucket_name character varying, placement character varying, size numeric, get numeric, put numeric, bytes_sent numeric) + LANGUAGE plpgsql + AS $$ + +DECLARE + _ds TIMESTAMP; + _df TIMESTAMP; + _days INT; + _hours INT; + +BEGIN +SELECT TO_TIMESTAMP(ds, 'YYYY-MM-DD HH24:MI:SS') INTO _ds; +SELECT TO_TIMESTAMP(df, 'YYYY-MM-DD HH24:MI:SS') INTO _df; +SELECT DATE_PART('day', _df - _ds) INTO _days; +SELECT CEIL(EXTRACT(EPOCH FROM (_df - _ds))/3600) INTO _hours; + +RETURN QUERY + +SELECT + s3billing.bucket_info.name AS bucket_name, + (CASE + WHEN ( s3billing.placement.name = 'default-placement') THEN 'HOT' + WHEN ( not s3billing.placement.name = 'default-placement' ) THEN s3billing.placement.name + END + ) AS placement + ,coalesce(ceil(sum(usage_rgw_main_size_actual)/_days)::numeric, 0) AS size + ,coalesce(s2.get, 0) AS get + ,coalesce(s2.put, 0) AS put + ,coalesce(s2.bytes_sent, 0) AS bytes_sent +FROM s3billing.bucket_stat +INNER JOIN s3billing.placement ON s3billing.bucket_stat.placement_id=s3billing.placement.id +INNER JOIN s3billing.bucket_info ON s3billing.bucket_stat.bucket_id=s3billing.bucket_info.id +LEFT JOIN ( + SELECT + s1.bucket_id AS bucket_id + ,s1.bucket_name AS bucket_name + ,(CASE + WHEN ( s1.placement = 'default-placement') THEN 'HOT' + WHEN ( not s1.placement = 'default-placement' ) THEN s1.placement + END + ) AS placement + ,coalesce(sum(s1.get) ,0) AS get + ,coalesce(sum(s1.put) ,0) AS put + ,coalesce(sum(s1.bytes_sent), 0) AS bytes_sent + FROM ( + SELECT + s3billing.bucket_info.id AS bucket_id + ,s3billing.bucket_info.name AS bucket_name + ,(CASE + WHEN ( s3billing.placement.name = 'default-placement') THEN 'HOT' + WHEN ( not s3billing.placement.name = 'default-placement' ) THEN s3billing.placement.name + END + ) AS placement + ,(CASE + WHEN ( s3billing.category.name LIKE 'get%' + OR s3billing.category.name LIKE 'head%' + OR s3billing.category.name LIKE 'options%' + ) THEN coalesce(sum(ops), 0) + END + ) AS get + ,(CASE + WHEN ( s3billing.category.name LIKE 'put%' + OR s3billing.category.name LIKE 'post%' + OR s3billing.category.name LIKE 'patch%' + OR s3billing.category.name LIKE 'list%' + ) THEN coalesce(sum(ops), 0) + END + ) AS put + ,coalesce(sum(usage_bucket_by_user.bytes_sent), 0) AS bytes_sent + + FROM + s3billing.usage_bucket_by_user + INNER JOIN s3billing.bucket_info ON s3billing.usage_bucket_by_user.bucketid = s3billing.bucket_info.id + INNER JOIN s3billing.placement ON s3billing.bucket_info.placement_id = s3billing.placement.id + INNER JOIN s3billing.user_info ON s3billing.usage_bucket_by_user.user_id = s3billing.user_info.id + INNER JOIN s3billing.category ON s3billing.usage_bucket_by_user.category_id = s3billing.category.id + + WHERE + s3billing.user_info.name=_user + AND s3billing.usage_bucket_by_user.time >= _ds + AND s3billing.usage_bucket_by_user.time < _df + GROUP BY + s3billing.bucket_info.name + ,s3billing.placement.name + ,s3billing.category.name + ,s3billing.bucket_info.id + ) AS s1 + + GROUP BY + s1.bucket_name + ,s1.bucket_id + ,s1.placement + + ORDER BY + s1.placement + ,s1.bucket_name + +) AS s2 ON s2.bucket_id = s3billing.bucket_stat.bucket_id +WHERE owner=_user + AND timestamp_addition >= _ds + AND timestamp_addition < _df +GROUP BY + s3billing.bucket_info.name + ,s3billing.placement.name + ,s3billing.bucket_stat.bucket_id + ,s2.get + ,s2.put + ,s2.bytes_sent +ORDER BY + s3billing.placement.name +,s3billing.bucket_info.name +; +END; +$$; + + +ALTER FUNCTION s3billing.billing_per_user_fix_pl_sv(ds character varying, df character varying, _user character varying) OWNER TO postgres; + +-- +-- TOC entry 262 (class 1255 OID 2436167) +-- Name: billing_per_user_summary(character varying, character varying, character varying); Type: FUNCTION; Schema: s3billing; Owner: dsorokin +-- + +CREATE FUNCTION s3billing.billing_per_user_summary(_ds character varying, _df character varying, _user character varying) RETURNS TABLE(placement character varying, size_gb numeric, get_10k numeric, put_10k numeric, bytes_sent_gb numeric) + LANGUAGE plpgsql + AS $$ +BEGIN +RETURN QUERY +( +select + billing_per_user_fix_pl.placement as placement, + (CASE + WHEN ( billing_per_user_fix_pl.placement = 'HOT' + ) THEN greatest(ceil(sum(size)/1024/1024/1024)-1,0) + WHEN ( not billing_per_user_fix_pl.placement = 'HOT' + ) THEN ceil(sum(size)/1024/1024/1024) + END) AS size_GB, + (CASE + WHEN ( billing_per_user_fix_pl.placement = 'HOT' + ) THEN greatest(ceil(sum(get)/10000)-10,0) + WHEN ( not billing_per_user_fix_pl.placement = 'HOT' + ) THEN ceil(sum(get)/10000) + END) AS get_10k, + (CASE + WHEN ( billing_per_user_fix_pl.placement = 'HOT' + ) THEN greatest(ceil(sum(put)/10000)-1,0) + WHEN ( not billing_per_user_fix_pl.placement = 'HOT' + ) THEN ceil(sum(put)/10000) + END) AS put_10k, + (CASE + WHEN ( billing_per_user_fix_pl.placement = 'HOT' + ) then greatest(ceil(sum(bytes_sent)/1024/1024/1024)-100,0) + WHEN ( not billing_per_user_fix_pl.placement = 'HOT' + ) THEN ceil(sum(bytes_sent)/1024/1024/1024) + END) AS bytes_sent_GB + from s3billing.billing_per_user_fix_pl(_ds,_df,_user) + group by billing_per_user_fix_pl.placement +UNION all +select + 'HOT_FREE_LIMIT' as placement, + '1' AS size_GB, + '10' AS get_10k, + '1' AS put_10k, + '100' AS bytes_sent_GB + ); +END; +$$; + + +ALTER FUNCTION s3billing.billing_per_user_summary(_ds character varying, _df character varying, _user character varying) OWNER TO dsorokin; + +-- +-- TOC entry 259 (class 1255 OID 2426971) +-- Name: billing_varchar(character varying, character varying, character varying); Type: FUNCTION; Schema: s3billing; Owner: dsorokin +-- + +CREATE FUNCTION s3billing.billing_varchar(_ds character varying, _df character varying, _user character varying) RETURNS TABLE(bucket_name character varying, placement character varying, size numeric, get numeric, put numeric, bytes_sent numeric) + LANGUAGE plpgsql + AS $$ +BEGIN +RETURN QUERY + +SELECT + s3billing.bucket_info.name AS bucket_name + ,s3billing.placement.name AS placement + ,coalesce(round(sum(usage_rgw_main_size_actual)/ + (SELECT (DATE_PART('day', + ((TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS')) + -TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS')) + )*24+ + DATE_PART('hour', + ((TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS')) + -TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS')) + ))) + + )::numeric,0) AS size + ,coalesce(s2.get, 0) AS get + ,coalesce(s2.put, 0) AS put + ,coalesce(s2.bytes_sent, 0) as bytes_sent +FROM s3billing.bucket_stat +INNER JOIN s3billing.placement ON s3billing.bucket_stat.placement_id=s3billing.placement.id +INNER JOIN s3billing.bucket_info ON s3billing.bucket_stat.bucket_id=s3billing.bucket_info.id +LEFT JOIN ( + SELECT + s1.bucket_id AS bucket_id + ,s1.bucket_name AS bucket_name + ,s1.placement AS placement + ,coalesce(sum(s1.get) ,0) AS get + ,coalesce(sum(s1.put) ,0) AS put + ,coalesce(sum(s1.bytes_sent), 0) AS bytes_sent + FROM ( + SELECT + s3billing.bucket_info.id AS bucket_id + ,s3billing.bucket_info.name AS bucket_name + ,s3billing.placement.name AS placement + ,(CASE + WHEN ( s3billing.category.name LIKE 'get%' + OR s3billing.category.name LIKE 'head%' + OR s3billing.category.name LIKE 'options%' + ) THEN coalesce(sum(ops), 0) + END) AS get + ,(CASE + WHEN ( s3billing.category.name LIKE 'put%' + OR s3billing.category.name LIKE 'post%' + OR s3billing.category.name LIKE 'patch%' + OR s3billing.category.name LIKE 'list%' + ) THEN coalesce(sum(ops), 0) + END) AS put + ,coalesce(sum(usage_bucket_by_user.bytes_sent), 0) AS bytes_sent + + FROM + s3billing.usage_bucket_by_user + INNER JOIN s3billing.bucket_info ON s3billing.usage_bucket_by_user.bucketid = s3billing.bucket_info.id + INNER JOIN s3billing.placement ON s3billing.bucket_info.placement_id = s3billing.placement.id + INNER JOIN s3billing.user_info ON s3billing.usage_bucket_by_user.user_id = s3billing.user_info.id + INNER JOIN s3billing.category ON s3billing.usage_bucket_by_user.category_id = s3billing.category.id + + WHERE + s3billing.user_info.name=_user + AND s3billing.usage_bucket_by_user.time >=TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS') + AND s3billing.usage_bucket_by_user.time < TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS') + GROUP BY + s3billing.bucket_info.name + ,s3billing.placement.name + ,s3billing.category.name + ,s3billing.bucket_info.id + ) AS s1 + + GROUP BY + s1.bucket_name + ,s1.bucket_id + ,s1.placement + + ORDER BY + s1.placement + ,s1.bucket_name + +) AS s2 ON s2.bucket_id = s3billing.bucket_stat.bucket_id +WHERE owner=_user + AND timestamp_addition >= TO_TIMESTAMP(_ds, 'YYYY-MM-DD HH24:MI:SS') + AND timestamp_addition < TO_TIMESTAMP(_df, 'YYYY-MM-DD HH24:MI:SS') +GROUP BY + s3billing.bucket_info.name + ,s3billing.placement.name + ,s3billing.bucket_stat.bucket_id + ,s2.get + ,s2.put + ,s2.bytes_sent +ORDER BY + s3billing.placement.name +,s3billing.bucket_info.name +; +END; +$$; + + +ALTER FUNCTION s3billing.billing_varchar(_ds character varying, _df character varying, _user character varying) OWNER TO dsorokin; + +-- +-- TOC entry 258 (class 1255 OID 5083308) +-- Name: buckets_current_stat(character varying); Type: FUNCTION; Schema: s3billing; Owner: dsorokin +-- + +CREATE FUNCTION s3billing.buckets_current_stat(_user character varying) RETURNS TABLE(name character varying, placement character varying, bucket_quota_enabled boolean, bucket_quota_max_size bigint, bucket_quota_max_objects bigint, usage_rgw_main_size_actual bigint, usage_rgw_main_num_objects bigint) + LANGUAGE plpgsql + AS $$ +BEGIN +RETURN QUERY +select + s3billing.bucket_info.name + ,(case + when ( s3billing.placement.name = 'default-placement') then 'HOT' + WHEN ( not s3billing.placement.name = 'default-placement' ) THEN s3billing.placement.name + end + ) as placement + ,s3billing.bucket_stat.bucket_quota_enabled + ,s3billing.bucket_stat.bucket_quota_max_size + ,s3billing.bucket_stat.bucket_quota_max_objects + ,s3billing.bucket_stat.usage_rgw_main_size_actual + ,s3billing.bucket_stat.usage_rgw_main_num_objects + from s3billing.bucket_stat + inner join s3billing.bucket_info on s3billing.bucket_stat.bucket_id= s3billing.bucket_info.id + inner join s3billing.placement on s3billing.bucket_info.placement_id = s3billing.placement.id + where owner=_user + and s3billing.bucket_stat.timestamp_addition=( + select max(s3billing.bucket_stat.timestamp_addition) from s3billing.bucket_stat + ) + order by s3billing.bucket_info.name, s3billing.bucket_stat.timestamp_addition +; +END; +$$; + + +ALTER FUNCTION s3billing.buckets_current_stat(_user character varying) OWNER TO dsorokin; + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- TOC entry 222 (class 1259 OID 1893983) +-- Name: capacity_resource; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE TABLE ngcloud_ru.capacity_resource ( + vdc_id uuid NOT NULL, + "timestamp" timestamp with time zone NOT NULL, + cpu_allocated integer NOT NULL, + cpu_limit integer NOT NULL, + cpu_reserved integer NOT NULL, + cpu_used integer NOT NULL, + cpu_speed integer NOT NULL, + mem_allocated integer NOT NULL, + mem_limit integer NOT NULL, + mem_reserved integer NOT NULL, + mem_used integer NOT NULL +); + + +ALTER TABLE ngcloud_ru.capacity_resource OWNER TO vc_billing; + +-- +-- TOC entry 223 (class 1259 OID 1893993) +-- Name: capacity_storage; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE TABLE ngcloud_ru.capacity_storage ( + vdc_id uuid NOT NULL, + storage_profile_types_id integer NOT NULL, + "timestamp" timestamp with time zone NOT NULL, + id uuid NOT NULL, + "limit" integer NOT NULL, + used integer NOT NULL +); + + +ALTER TABLE ngcloud_ru.capacity_storage OWNER TO vc_billing; + +-- +-- TOC entry 220 (class 1259 OID 1893965) +-- Name: storage_profile_types; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE TABLE ngcloud_ru.storage_profile_types ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + + +ALTER TABLE ngcloud_ru.storage_profile_types OWNER TO vc_billing; + +-- +-- TOC entry 219 (class 1259 OID 1893964) +-- Name: storage_profile_types_id_seq; Type: SEQUENCE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE SEQUENCE ngcloud_ru.storage_profile_types_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE ngcloud_ru.storage_profile_types_id_seq OWNER TO vc_billing; + +-- +-- TOC entry 3486 (class 0 OID 0) +-- Dependencies: 219 +-- Name: storage_profile_types_id_seq; Type: SEQUENCE OWNED BY; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER SEQUENCE ngcloud_ru.storage_profile_types_id_seq OWNED BY ngcloud_ru.storage_profile_types.id; + + +-- +-- TOC entry 218 (class 1259 OID 1893959) +-- Name: tenant; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE TABLE ngcloud_ru.tenant ( + id uuid NOT NULL, + name character varying(255) NOT NULL, + wzcode bigint +); + + +ALTER TABLE ngcloud_ru.tenant OWNER TO vc_billing; + +-- +-- TOC entry 221 (class 1259 OID 1893973) +-- Name: vdc; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE TABLE ngcloud_ru.vdc ( + id uuid NOT NULL, + tenant_id uuid NOT NULL, + name character varying(255) NOT NULL +); + + +ALTER TABLE ngcloud_ru.vdc OWNER TO vc_billing; + +-- +-- TOC entry 230 (class 1259 OID 2160668) +-- Name: bucket_info; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.bucket_info ( + id integer NOT NULL, + bucket_id character varying(255) NOT NULL, + name character varying(255) NOT NULL, + marker character varying(255) NOT NULL, + placement_id bigint DEFAULT 0 NOT NULL +); + + +ALTER TABLE s3billing.bucket_info OWNER TO s3billing; + +-- +-- TOC entry 229 (class 1259 OID 2160667) +-- Name: bucket_info_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.bucket_info_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.bucket_info_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3490 (class 0 OID 0) +-- Dependencies: 229 +-- Name: bucket_info_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.bucket_info_id_seq OWNED BY s3billing.bucket_info.id; + + +-- +-- TOC entry 226 (class 1259 OID 2160642) +-- Name: bucket_stat; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.bucket_stat ( + bucket_id bigint, + num_shards bigint NOT NULL, + tenant character varying(255) DEFAULT NULL::character varying, + zone_group bigint NOT NULL, + placement_id bigint NOT NULL, + explicit_placement_data_pool character varying(255) DEFAULT NULL::character varying, + explicit_placement_data_extra_pool character varying(255) DEFAULT NULL::character varying, + explicit_placement_index_pool character varying(255) DEFAULT NULL::character varying, + index_type_id bigint NOT NULL, + versioned boolean DEFAULT false, + versioning_enabled boolean DEFAULT false, + object_lock_enabled boolean DEFAULT false, + mfa_enabled boolean DEFAULT false, + owner character varying(255) NOT NULL, + bucket_quota_enabled boolean DEFAULT false, + bucket_quota_check_on_raw boolean DEFAULT false, + bucket_quota_max_size bigint NOT NULL, + bucket_quota_max_size_kb bigint NOT NULL, + bucket_quota_max_objects bigint NOT NULL, + usage_rgw_main_size bigint NOT NULL, + usage_rgw_main_size_actual bigint NOT NULL, + usage_rgw_main_size_utilized bigint NOT NULL, + usage_rgw_main_size_kb bigint NOT NULL, + usage_rgw_main_size_kb_actual bigint NOT NULL, + usage_rgw_main_size_kb_utilized bigint NOT NULL, + usage_rgw_main_num_objects bigint NOT NULL, + usage_rgw_multimeta_size bigint, + usage_rgw_multimeta_size_actual bigint, + usage_rgw_multimeta_size_utilized bigint, + usage_rgw_multimeta_size_kb bigint, + usage_rgw_multimeta_size_kb_actual bigint, + usage_rgw_multimeta_size_kb_utilized bigint, + usage_rgw_multimeta_num_objects bigint, + creation_time timestamp without time zone NOT NULL, + mtime timestamp without time zone NOT NULL, + timestamp_addition timestamp without time zone DEFAULT date_trunc('hour'::text, CURRENT_TIMESTAMP) +); + + +ALTER TABLE s3billing.bucket_stat OWNER TO s3billing; + +-- +-- TOC entry 245 (class 1259 OID 2160763) +-- Name: category; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.category ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + + +ALTER TABLE s3billing.category OWNER TO s3billing; + +-- +-- TOC entry 244 (class 1259 OID 2160762) +-- Name: category_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.category_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.category_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3493 (class 0 OID 0) +-- Dependencies: 244 +-- Name: category_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.category_id_seq OWNED BY s3billing.category.id; + + +-- +-- TOC entry 225 (class 1259 OID 2160635) +-- Name: goose_db_version; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.goose_db_version ( + id integer NOT NULL, + version_id bigint NOT NULL, + is_applied boolean NOT NULL, + tstamp timestamp without time zone DEFAULT now() NOT NULL +); + + +ALTER TABLE s3billing.goose_db_version OWNER TO s3billing; + +-- +-- TOC entry 224 (class 1259 OID 2160634) +-- Name: goose_db_version_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE s3billing.goose_db_version ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME s3billing.goose_db_version_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- TOC entry 234 (class 1259 OID 2160684) +-- Name: index_type; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.index_type ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + + +ALTER TABLE s3billing.index_type OWNER TO s3billing; + +-- +-- TOC entry 233 (class 1259 OID 2160683) +-- Name: index_type_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.index_type_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.index_type_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3496 (class 0 OID 0) +-- Dependencies: 233 +-- Name: index_type_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.index_type_id_seq OWNED BY s3billing.index_type.id; + + +-- +-- TOC entry 232 (class 1259 OID 2160677) +-- Name: placement; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.placement ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + + +ALTER TABLE s3billing.placement OWNER TO s3billing; + +-- +-- TOC entry 231 (class 1259 OID 2160676) +-- Name: placement_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.placement_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.placement_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3498 (class 0 OID 0) +-- Dependencies: 231 +-- Name: placement_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.placement_id_seq OWNED BY s3billing.placement.id; + + +-- +-- TOC entry 239 (class 1259 OID 2160705) +-- Name: usage_bucket_by_user; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.usage_bucket_by_user ( + bucketid bigint, + "time" timestamp without time zone NOT NULL, + bytes_sent bigint NOT NULL, + bytes_received bigint NOT NULL, + ops bigint NOT NULL, + successful_ops bigint NOT NULL, + date_start timestamp without time zone NOT NULL, + date_end timestamp without time zone NOT NULL, + user_id bigint NOT NULL, + category_id bigint NOT NULL +); + + +ALTER TABLE s3billing.usage_bucket_by_user OWNER TO s3billing; + +-- +-- TOC entry 238 (class 1259 OID 2160698) +-- Name: usage_stat_summary; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.usage_stat_summary ( + id integer NOT NULL, + userid character varying(255) NOT NULL, + category character varying(255) NOT NULL, + bytes_sent bigint NOT NULL, + bytes_received bigint NOT NULL, + ops bigint NOT NULL, + successful_ops bigint NOT NULL, + date_start timestamp without time zone NOT NULL, + date_end timestamp without time zone NOT NULL +); + + +ALTER TABLE s3billing.usage_stat_summary OWNER TO s3billing; + +-- +-- TOC entry 237 (class 1259 OID 2160697) +-- Name: usage_stat_summary_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.usage_stat_summary_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.usage_stat_summary_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3501 (class 0 OID 0) +-- Dependencies: 237 +-- Name: usage_stat_summary_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.usage_stat_summary_id_seq OWNED BY s3billing.usage_stat_summary.id; + + +-- +-- TOC entry 236 (class 1259 OID 2160691) +-- Name: usage_stat_total; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.usage_stat_total ( + id integer NOT NULL, + userid character varying(255) NOT NULL, + bytes_sent bigint NOT NULL, + bytes_received bigint NOT NULL, + ops bigint NOT NULL, + successful_ops bigint NOT NULL, + date_start timestamp without time zone NOT NULL, + date_end timestamp without time zone NOT NULL +); + + +ALTER TABLE s3billing.usage_stat_total OWNER TO s3billing; + +-- +-- TOC entry 235 (class 1259 OID 2160690) +-- Name: usage_stat_total_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.usage_stat_total_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.usage_stat_total_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3503 (class 0 OID 0) +-- Dependencies: 235 +-- Name: usage_stat_total_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.usage_stat_total_id_seq OWNED BY s3billing.usage_stat_total.id; + + +-- +-- TOC entry 243 (class 1259 OID 2160751) +-- Name: user_info; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.user_info ( + id integer NOT NULL, + name character varying(255) NOT NULL, + owner character varying(255) NOT NULL +); + + +ALTER TABLE s3billing.user_info OWNER TO s3billing; + +-- +-- TOC entry 242 (class 1259 OID 2160750) +-- Name: user_info_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.user_info_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.user_info_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3505 (class 0 OID 0) +-- Dependencies: 242 +-- Name: user_info_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.user_info_id_seq OWNED BY s3billing.user_info.id; + + +-- +-- TOC entry 241 (class 1259 OID 2160712) +-- Name: user_quota_bucket; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.user_quota_bucket ( + id integer NOT NULL, + userid character varying(255) NOT NULL, + enabled boolean DEFAULT false, + check_on_raw boolean DEFAULT false, + max_size bigint NOT NULL, + max_size_kb bigint NOT NULL, + max_objects bigint NOT NULL +); + + +ALTER TABLE s3billing.user_quota_bucket OWNER TO s3billing; + +-- +-- TOC entry 240 (class 1259 OID 2160711) +-- Name: user_quota_bucket_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.user_quota_bucket_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.user_quota_bucket_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3507 (class 0 OID 0) +-- Dependencies: 240 +-- Name: user_quota_bucket_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.user_quota_bucket_id_seq OWNED BY s3billing.user_quota_bucket.id; + + +-- +-- TOC entry 228 (class 1259 OID 2160661) +-- Name: zone_group; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.zone_group ( + id integer NOT NULL, + name uuid NOT NULL +); + + +ALTER TABLE s3billing.zone_group OWNER TO s3billing; + +-- +-- TOC entry 227 (class 1259 OID 2160660) +-- Name: zone_group_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.zone_group_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.zone_group_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3509 (class 0 OID 0) +-- Dependencies: 227 +-- Name: zone_group_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.zone_group_id_seq OWNED BY s3billing.zone_group.id; + + +-- +-- TOC entry 3262 (class 2604 OID 1893968) +-- Name: storage_profile_types id; Type: DEFAULT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.storage_profile_types ALTER COLUMN id SET DEFAULT nextval('ngcloud_ru.storage_profile_types_id_seq'::regclass); + + +-- +-- TOC entry 3276 (class 2604 OID 2160671) +-- Name: bucket_info id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.bucket_info ALTER COLUMN id SET DEFAULT nextval('s3billing.bucket_info_id_seq'::regclass); + + +-- +-- TOC entry 3286 (class 2604 OID 2160766) +-- Name: category id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.category ALTER COLUMN id SET DEFAULT nextval('s3billing.category_id_seq'::regclass); + + +-- +-- TOC entry 3279 (class 2604 OID 2160687) +-- Name: index_type id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.index_type ALTER COLUMN id SET DEFAULT nextval('s3billing.index_type_id_seq'::regclass); + + +-- +-- TOC entry 3278 (class 2604 OID 2160680) +-- Name: placement id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.placement ALTER COLUMN id SET DEFAULT nextval('s3billing.placement_id_seq'::regclass); + + +-- +-- TOC entry 3281 (class 2604 OID 2160701) +-- Name: usage_stat_summary id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_stat_summary ALTER COLUMN id SET DEFAULT nextval('s3billing.usage_stat_summary_id_seq'::regclass); + + +-- +-- TOC entry 3280 (class 2604 OID 2160694) +-- Name: usage_stat_total id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_stat_total ALTER COLUMN id SET DEFAULT nextval('s3billing.usage_stat_total_id_seq'::regclass); + + +-- +-- TOC entry 3285 (class 2604 OID 2160754) +-- Name: user_info id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.user_info ALTER COLUMN id SET DEFAULT nextval('s3billing.user_info_id_seq'::regclass); + + +-- +-- TOC entry 3282 (class 2604 OID 2160715) +-- Name: user_quota_bucket id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.user_quota_bucket ALTER COLUMN id SET DEFAULT nextval('s3billing.user_quota_bucket_id_seq'::regclass); + + +-- +-- TOC entry 3275 (class 2604 OID 2160664) +-- Name: zone_group id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.zone_group ALTER COLUMN id SET DEFAULT nextval('s3billing.zone_group_id_seq'::regclass); + + +-- +-- TOC entry 3296 (class 2606 OID 1893987) +-- Name: capacity_resource capacity_resource_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_resource + ADD CONSTRAINT capacity_resource_pkey PRIMARY KEY (vdc_id, "timestamp"); + + +-- +-- TOC entry 3298 (class 2606 OID 1893997) +-- Name: capacity_storage capacity_storage_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_storage + ADD CONSTRAINT capacity_storage_pkey PRIMARY KEY (vdc_id, id, "timestamp"); + + +-- +-- TOC entry 3290 (class 2606 OID 1893972) +-- Name: storage_profile_types storage_profile_types_name_key; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.storage_profile_types + ADD CONSTRAINT storage_profile_types_name_key UNIQUE (name); + + +-- +-- TOC entry 3292 (class 2606 OID 1893970) +-- Name: storage_profile_types storage_profile_types_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.storage_profile_types + ADD CONSTRAINT storage_profile_types_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3288 (class 2606 OID 1893963) +-- Name: tenant tenant_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.tenant + ADD CONSTRAINT tenant_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3294 (class 2606 OID 1893977) +-- Name: vdc vdc_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.vdc + ADD CONSTRAINT vdc_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3308 (class 2606 OID 2160675) +-- Name: bucket_info bucket_info_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.bucket_info + ADD CONSTRAINT bucket_info_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3303 (class 2606 OID 2476484) +-- Name: bucket_stat bucket_stat_unique; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.bucket_stat + ADD CONSTRAINT bucket_stat_unique UNIQUE (bucket_id, placement_id, timestamp_addition); + + +-- +-- TOC entry 3328 (class 2606 OID 2160768) +-- Name: category category_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.category + ADD CONSTRAINT category_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3300 (class 2606 OID 2160640) +-- Name: goose_db_version goose_db_version_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.goose_db_version + ADD CONSTRAINT goose_db_version_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3314 (class 2606 OID 2160689) +-- Name: index_type index_type_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.index_type + ADD CONSTRAINT index_type_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3312 (class 2606 OID 2160682) +-- Name: placement placement_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.placement + ADD CONSTRAINT placement_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3320 (class 2606 OID 2476705) +-- Name: usage_bucket_by_user usage_bucket_by_user_unique; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_bucket_by_user + ADD CONSTRAINT usage_bucket_by_user_unique UNIQUE (bucketid, date_start, date_end, user_id, category_id); + + +-- +-- TOC entry 3318 (class 2606 OID 2160703) +-- Name: usage_stat_summary usage_stat_summary_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_stat_summary + ADD CONSTRAINT usage_stat_summary_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3316 (class 2606 OID 2160696) +-- Name: usage_stat_total usage_stat_total_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_stat_total + ADD CONSTRAINT usage_stat_total_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3325 (class 2606 OID 2160758) +-- Name: user_info user_info_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.user_info + ADD CONSTRAINT user_info_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3322 (class 2606 OID 2160719) +-- Name: user_quota_bucket user_quota_bucket_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.user_quota_bucket + ADD CONSTRAINT user_quota_bucket_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3305 (class 2606 OID 2160666) +-- Name: zone_group zone_group_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.zone_group + ADD CONSTRAINT zone_group_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3306 (class 1259 OID 2474077) +-- Name: bucket_info_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX bucket_info_name_idx ON s3billing.bucket_info USING btree (name); + + +-- +-- TOC entry 3309 (class 1259 OID 2474078) +-- Name: bucket_info_placement_id_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX bucket_info_placement_id_idx ON s3billing.bucket_info USING btree (placement_id); + + +-- +-- TOC entry 3301 (class 1259 OID 2474094) +-- Name: bucket_stat_owner_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX bucket_stat_owner_idx ON s3billing.bucket_stat USING btree (owner); + + +-- +-- TOC entry 3326 (class 1259 OID 2474445) +-- Name: category_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE UNIQUE INDEX category_name_idx ON s3billing.category USING btree (name); + + +-- +-- TOC entry 3310 (class 1259 OID 2474468) +-- Name: placement_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE UNIQUE INDEX placement_name_idx ON s3billing.placement USING btree (name); + + +-- +-- TOC entry 3323 (class 1259 OID 2474438) +-- Name: user_info_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX user_info_name_idx ON s3billing.user_info USING btree (name); + + +-- +-- TOC entry 3330 (class 2606 OID 1893988) +-- Name: capacity_resource capacity_resource_vdc_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_resource + ADD CONSTRAINT capacity_resource_vdc_id_fkey FOREIGN KEY (vdc_id) REFERENCES ngcloud_ru.vdc(id) ON DELETE CASCADE; + + +-- +-- TOC entry 3331 (class 2606 OID 1894003) +-- Name: capacity_storage capacity_storage_storage_profile_types_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_storage + ADD CONSTRAINT capacity_storage_storage_profile_types_id_fkey FOREIGN KEY (storage_profile_types_id) REFERENCES ngcloud_ru.storage_profile_types(id); + + +-- +-- TOC entry 3332 (class 2606 OID 1893998) +-- Name: capacity_storage capacity_storage_vdc_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_storage + ADD CONSTRAINT capacity_storage_vdc_id_fkey FOREIGN KEY (vdc_id) REFERENCES ngcloud_ru.vdc(id) ON DELETE CASCADE; + + +-- +-- TOC entry 3329 (class 2606 OID 1893978) +-- Name: vdc vdc_tenant_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.vdc + ADD CONSTRAINT vdc_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES ngcloud_ru.tenant(id); + + +-- +-- TOC entry 3481 (class 0 OID 0) +-- Dependencies: 7 +-- Name: SCHEMA ngcloud_ru; Type: ACL; Schema: -; Owner: vc_billing +-- + +GRANT USAGE ON SCHEMA ngcloud_ru TO grafanabilling; + + +-- +-- TOC entry 3482 (class 0 OID 0) +-- Dependencies: 8 +-- Name: SCHEMA s3billing; Type: ACL; Schema: -; Owner: s3billing +-- + +GRANT USAGE ON SCHEMA s3billing TO grafanabilling; + + +-- +-- TOC entry 3483 (class 0 OID 0) +-- Dependencies: 222 +-- Name: TABLE capacity_resource; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing +-- + +GRANT SELECT ON TABLE ngcloud_ru.capacity_resource TO grafanabilling; + + +-- +-- TOC entry 3484 (class 0 OID 0) +-- Dependencies: 223 +-- Name: TABLE capacity_storage; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing +-- + +GRANT SELECT ON TABLE ngcloud_ru.capacity_storage TO grafanabilling; + + +-- +-- TOC entry 3485 (class 0 OID 0) +-- Dependencies: 220 +-- Name: TABLE storage_profile_types; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing +-- + +GRANT SELECT ON TABLE ngcloud_ru.storage_profile_types TO grafanabilling; + + +-- +-- TOC entry 3487 (class 0 OID 0) +-- Dependencies: 218 +-- Name: TABLE tenant; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing +-- + +GRANT SELECT ON TABLE ngcloud_ru.tenant TO grafanabilling; + + +-- +-- TOC entry 3488 (class 0 OID 0) +-- Dependencies: 221 +-- Name: TABLE vdc; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing +-- + +GRANT SELECT ON TABLE ngcloud_ru.vdc TO grafanabilling; + + +-- +-- TOC entry 3489 (class 0 OID 0) +-- Dependencies: 230 +-- Name: TABLE bucket_info; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.bucket_info TO grafanabilling; + + +-- +-- TOC entry 3491 (class 0 OID 0) +-- Dependencies: 226 +-- Name: TABLE bucket_stat; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.bucket_stat TO grafanabilling; + + +-- +-- TOC entry 3492 (class 0 OID 0) +-- Dependencies: 245 +-- Name: TABLE category; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.category TO grafanabilling; + + +-- +-- TOC entry 3494 (class 0 OID 0) +-- Dependencies: 225 +-- Name: TABLE goose_db_version; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.goose_db_version TO grafanabilling; + + +-- +-- TOC entry 3495 (class 0 OID 0) +-- Dependencies: 234 +-- Name: TABLE index_type; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.index_type TO grafanabilling; + + +-- +-- TOC entry 3497 (class 0 OID 0) +-- Dependencies: 232 +-- Name: TABLE placement; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.placement TO grafanabilling; + + +-- +-- TOC entry 3499 (class 0 OID 0) +-- Dependencies: 239 +-- Name: TABLE usage_bucket_by_user; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.usage_bucket_by_user TO grafanabilling; + + +-- +-- TOC entry 3500 (class 0 OID 0) +-- Dependencies: 238 +-- Name: TABLE usage_stat_summary; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.usage_stat_summary TO grafanabilling; + + +-- +-- TOC entry 3502 (class 0 OID 0) +-- Dependencies: 236 +-- Name: TABLE usage_stat_total; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.usage_stat_total TO grafanabilling; + + +-- +-- TOC entry 3504 (class 0 OID 0) +-- Dependencies: 243 +-- Name: TABLE user_info; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.user_info TO grafanabilling; + + +-- +-- TOC entry 3506 (class 0 OID 0) +-- Dependencies: 241 +-- Name: TABLE user_quota_bucket; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.user_quota_bucket TO grafanabilling; + + +-- +-- TOC entry 3508 (class 0 OID 0) +-- Dependencies: 228 +-- Name: TABLE zone_group; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.zone_group TO grafanabilling; + + +-- Completed on 2025-10-24 14:30:47 + +-- +-- PostgreSQL database dump complete +-- + +\unrestrict M18FnaokuZFKQZjWu9az6dzOO6o2cSlpJgAocs2PXfRbmzHVcXEXaiZZcaOPZko + diff --git a/research/payg-sso-full/etc/db/billing_schema_dev.sql b/research/payg-sso-full/etc/db/billing_schema_dev.sql new file mode 100644 index 0000000..3ac43c9 --- /dev/null +++ b/research/payg-sso-full/etc/db/billing_schema_dev.sql @@ -0,0 +1,72 @@ +set role postgres; +-- +CREATE SCHEMA IF NOT EXISTS gpu; +--ALTER SCHEMA gpu OWNER TO dbo; +GRANT USAGE ON SCHEMA gpu TO nifi; + +GRANT ALL ON ALL TABLES IN SCHEMA gpu TO nifi; +GRANT ALL ON ALL SEQUENCES IN SCHEMA gpu TO nifi; + +--ALTER DEFAULT PRIVILEGES IN SCHEMA gpu GRANT ALL ON TABLES TO nifi; +--ALTER DEFAULT PRIVILEGES IN SCHEMA gpu GRANT ALL ON SEQUENCES TO nifi; + +ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres IN SCHEMA gpu GRANT ALL ON TABLES TO nifi; +ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres IN SCHEMA gpu GRANT ALL ON SEQUENCES TO nifi; + +--SET ROLE dbo; + +DROP TABLE IF EXISTS gpu.vm; +CREATE TABLE gpu.vm ( + objUUID uuid NOT NULL PRIMARY KEY + ,groupUUID uuid NULL + ,objId varchar(255) NULL + ,ClientID varchar(255) NULL -- WZ + ,VCD varchar(255) NULL + ,Org varchar(255) NULL + ,OrgVDC varchar(255) NULL + ,vCenter varchar(255) NULL + ,GPU varchar(255) NULL + ,dt_load timestamptz NOT NULL +); +ALTER TABLE gpu.vm OWNER TO dbo; +/* +{ +"type": "record", +"name": "gpu.vm", +"namespace": "org.apache.nifi", +"fields": [ + {"name":"objUUID", "type":{"type": "string", "logicalType": "uuid"}}, + {"name":"groupUUID", "type":[{"type": "string", "logicalType": "uuid"} ,"null"]}, + {"name":"objId", "type":["string" ,"null"]}, + {"name":"ClientID", "type":["int" ,"null"]}, + {"name":"VCD", "type":["string" ,"null"]}, + {"name":"Org", "type":["string" ,"null"]}, + {"name":"OrgVDC", "type":["string" ,"null"]}, + {"name":"vCenter", "type":["string" ,"null"]}, + {"name":"GPU", "type":["string" ,"null"]}, + {"name":"VCD", "type":["string" ,"null"]}, + {"name":"dt_load","type":{"type": "long", "logicalType": "local-timestamp-millis"}} +] +} +*/ + +DROP TABLE IF EXISTS gpu.vm_power_state; +CREATE TABLE gpu.vm_power_state ( + objId varchar(255) NULL + ,ts timestamptz NOT NULL -- без таймштампа загрузки + ,value int NULL + ,CONSTRAINT PK_vm_power_state PRIMARY KEY(objId, ts) +); +ALTER TABLE gpu.vm_power_state OWNER TO dbo; +/* +{ +"type": "record", +"name": "gpu.vm_power_state, +"namespace": "org.apache.nifi", +"fields": [ + {"name":"objId", "type":["string" ,"null"]}, + {"name":"ts","type":{"type": "long", "logicalType": "local-timestamp-millis"}}, + {"name":"value", "type":["int" ,"null"]} +] +} +*/ \ No newline at end of file diff --git a/research/payg-sso-full/etc/db/billing_schema_s3.sql b/research/payg-sso-full/etc/db/billing_schema_s3.sql new file mode 100644 index 0000000..6382912 --- /dev/null +++ b/research/payg-sso-full/etc/db/billing_schema_s3.sql @@ -0,0 +1,828 @@ +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 16.0 +-- Dumped by pg_dump version 16.4 + +-- Started on 2025-09-15 09:50:58 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- TOC entry 230 (class 1259 OID 2160668) +-- Name: bucket_info; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.bucket_info ( + id integer NOT NULL, + bucket_id character varying(255) NOT NULL, + name character varying(255) NOT NULL, + marker character varying(255) NOT NULL, + placement_id bigint DEFAULT 0 NOT NULL +); + + +ALTER TABLE s3billing.bucket_info OWNER TO s3billing; + +-- +-- TOC entry 229 (class 1259 OID 2160667) +-- Name: bucket_info_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.bucket_info_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.bucket_info_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3448 (class 0 OID 0) +-- Dependencies: 229 +-- Name: bucket_info_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.bucket_info_id_seq OWNED BY s3billing.bucket_info.id; + + +-- +-- TOC entry 226 (class 1259 OID 2160642) +-- Name: bucket_stat; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.bucket_stat ( + bucket_id bigint, + num_shards bigint NOT NULL, + tenant character varying(255) DEFAULT NULL::character varying, + zone_group bigint NOT NULL, + placement_id bigint NOT NULL, + explicit_placement_data_pool character varying(255) DEFAULT NULL::character varying, + explicit_placement_data_extra_pool character varying(255) DEFAULT NULL::character varying, + explicit_placement_index_pool character varying(255) DEFAULT NULL::character varying, + index_type_id bigint NOT NULL, + versioned boolean DEFAULT false, + versioning_enabled boolean DEFAULT false, + object_lock_enabled boolean DEFAULT false, + mfa_enabled boolean DEFAULT false, + owner character varying(255) NOT NULL, + bucket_quota_enabled boolean DEFAULT false, + bucket_quota_check_on_raw boolean DEFAULT false, + bucket_quota_max_size bigint NOT NULL, + bucket_quota_max_size_kb bigint NOT NULL, + bucket_quota_max_objects bigint NOT NULL, + usage_rgw_main_size bigint NOT NULL, + usage_rgw_main_size_actual bigint NOT NULL, + usage_rgw_main_size_utilized bigint NOT NULL, + usage_rgw_main_size_kb bigint NOT NULL, + usage_rgw_main_size_kb_actual bigint NOT NULL, + usage_rgw_main_size_kb_utilized bigint NOT NULL, + usage_rgw_main_num_objects bigint NOT NULL, + usage_rgw_multimeta_size bigint, + usage_rgw_multimeta_size_actual bigint, + usage_rgw_multimeta_size_utilized bigint, + usage_rgw_multimeta_size_kb bigint, + usage_rgw_multimeta_size_kb_actual bigint, + usage_rgw_multimeta_size_kb_utilized bigint, + usage_rgw_multimeta_num_objects bigint, + creation_time timestamp without time zone NOT NULL, + mtime timestamp without time zone NOT NULL, + timestamp_addition timestamp without time zone DEFAULT date_trunc('hour'::text, CURRENT_TIMESTAMP) +); + + +ALTER TABLE s3billing.bucket_stat OWNER TO s3billing; + +-- +-- TOC entry 245 (class 1259 OID 2160763) +-- Name: category; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.category ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + + +ALTER TABLE s3billing.category OWNER TO s3billing; + +-- +-- TOC entry 244 (class 1259 OID 2160762) +-- Name: category_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.category_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.category_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3451 (class 0 OID 0) +-- Dependencies: 244 +-- Name: category_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.category_id_seq OWNED BY s3billing.category.id; + + +-- +-- TOC entry 225 (class 1259 OID 2160635) +-- Name: goose_db_version; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.goose_db_version ( + id integer NOT NULL, + version_id bigint NOT NULL, + is_applied boolean NOT NULL, + tstamp timestamp without time zone DEFAULT now() NOT NULL +); + + +ALTER TABLE s3billing.goose_db_version OWNER TO s3billing; + +-- +-- TOC entry 224 (class 1259 OID 2160634) +-- Name: goose_db_version_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE s3billing.goose_db_version ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME s3billing.goose_db_version_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- TOC entry 234 (class 1259 OID 2160684) +-- Name: index_type; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.index_type ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + + +ALTER TABLE s3billing.index_type OWNER TO s3billing; + +-- +-- TOC entry 233 (class 1259 OID 2160683) +-- Name: index_type_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.index_type_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.index_type_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3454 (class 0 OID 0) +-- Dependencies: 233 +-- Name: index_type_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.index_type_id_seq OWNED BY s3billing.index_type.id; + + +-- +-- TOC entry 232 (class 1259 OID 2160677) +-- Name: placement; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.placement ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + + +ALTER TABLE s3billing.placement OWNER TO s3billing; + +-- +-- TOC entry 231 (class 1259 OID 2160676) +-- Name: placement_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.placement_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.placement_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3456 (class 0 OID 0) +-- Dependencies: 231 +-- Name: placement_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.placement_id_seq OWNED BY s3billing.placement.id; + + +-- +-- TOC entry 239 (class 1259 OID 2160705) +-- Name: usage_bucket_by_user; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.usage_bucket_by_user ( + bucketid bigint, + "time" timestamp without time zone NOT NULL, + bytes_sent bigint NOT NULL, + bytes_received bigint NOT NULL, + ops bigint NOT NULL, + successful_ops bigint NOT NULL, + date_start timestamp without time zone NOT NULL, + date_end timestamp without time zone NOT NULL, + user_id bigint NOT NULL, + category_id bigint NOT NULL +); + + +ALTER TABLE s3billing.usage_bucket_by_user OWNER TO s3billing; + +-- +-- TOC entry 238 (class 1259 OID 2160698) +-- Name: usage_stat_summary; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.usage_stat_summary ( + id integer NOT NULL, + userid character varying(255) NOT NULL, + category character varying(255) NOT NULL, + bytes_sent bigint NOT NULL, + bytes_received bigint NOT NULL, + ops bigint NOT NULL, + successful_ops bigint NOT NULL, + date_start timestamp without time zone NOT NULL, + date_end timestamp without time zone NOT NULL +); + + +ALTER TABLE s3billing.usage_stat_summary OWNER TO s3billing; + +-- +-- TOC entry 237 (class 1259 OID 2160697) +-- Name: usage_stat_summary_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.usage_stat_summary_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.usage_stat_summary_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3459 (class 0 OID 0) +-- Dependencies: 237 +-- Name: usage_stat_summary_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.usage_stat_summary_id_seq OWNED BY s3billing.usage_stat_summary.id; + + +-- +-- TOC entry 236 (class 1259 OID 2160691) +-- Name: usage_stat_total; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.usage_stat_total ( + id integer NOT NULL, + userid character varying(255) NOT NULL, + bytes_sent bigint NOT NULL, + bytes_received bigint NOT NULL, + ops bigint NOT NULL, + successful_ops bigint NOT NULL, + date_start timestamp without time zone NOT NULL, + date_end timestamp without time zone NOT NULL +); + + +ALTER TABLE s3billing.usage_stat_total OWNER TO s3billing; + +-- +-- TOC entry 235 (class 1259 OID 2160690) +-- Name: usage_stat_total_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.usage_stat_total_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.usage_stat_total_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3461 (class 0 OID 0) +-- Dependencies: 235 +-- Name: usage_stat_total_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.usage_stat_total_id_seq OWNED BY s3billing.usage_stat_total.id; + + +-- +-- TOC entry 243 (class 1259 OID 2160751) +-- Name: user_info; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.user_info ( + id integer NOT NULL, + name character varying(255) NOT NULL, + owner character varying(255) NOT NULL +); + + +ALTER TABLE s3billing.user_info OWNER TO s3billing; + +-- +-- TOC entry 242 (class 1259 OID 2160750) +-- Name: user_info_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.user_info_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.user_info_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3463 (class 0 OID 0) +-- Dependencies: 242 +-- Name: user_info_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.user_info_id_seq OWNED BY s3billing.user_info.id; + + +-- +-- TOC entry 241 (class 1259 OID 2160712) +-- Name: user_quota_bucket; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.user_quota_bucket ( + id integer NOT NULL, + userid character varying(255) NOT NULL, + enabled boolean DEFAULT false, + check_on_raw boolean DEFAULT false, + max_size bigint NOT NULL, + max_size_kb bigint NOT NULL, + max_objects bigint NOT NULL +); + + +ALTER TABLE s3billing.user_quota_bucket OWNER TO s3billing; + +-- +-- TOC entry 240 (class 1259 OID 2160711) +-- Name: user_quota_bucket_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.user_quota_bucket_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.user_quota_bucket_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3465 (class 0 OID 0) +-- Dependencies: 240 +-- Name: user_quota_bucket_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.user_quota_bucket_id_seq OWNED BY s3billing.user_quota_bucket.id; + + +-- +-- TOC entry 228 (class 1259 OID 2160661) +-- Name: zone_group; Type: TABLE; Schema: s3billing; Owner: s3billing +-- + +CREATE TABLE s3billing.zone_group ( + id integer NOT NULL, + name uuid NOT NULL +); + + +ALTER TABLE s3billing.zone_group OWNER TO s3billing; + +-- +-- TOC entry 227 (class 1259 OID 2160660) +-- Name: zone_group_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing +-- + +CREATE SEQUENCE s3billing.zone_group_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE s3billing.zone_group_id_seq OWNER TO s3billing; + +-- +-- TOC entry 3467 (class 0 OID 0) +-- Dependencies: 227 +-- Name: zone_group_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing +-- + +ALTER SEQUENCE s3billing.zone_group_id_seq OWNED BY s3billing.zone_group.id; + + +-- +-- TOC entry 3258 (class 2604 OID 2160671) +-- Name: bucket_info id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.bucket_info ALTER COLUMN id SET DEFAULT nextval('s3billing.bucket_info_id_seq'::regclass); + + +-- +-- TOC entry 3268 (class 2604 OID 2160766) +-- Name: category id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.category ALTER COLUMN id SET DEFAULT nextval('s3billing.category_id_seq'::regclass); + + +-- +-- TOC entry 3261 (class 2604 OID 2160687) +-- Name: index_type id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.index_type ALTER COLUMN id SET DEFAULT nextval('s3billing.index_type_id_seq'::regclass); + + +-- +-- TOC entry 3260 (class 2604 OID 2160680) +-- Name: placement id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.placement ALTER COLUMN id SET DEFAULT nextval('s3billing.placement_id_seq'::regclass); + + +-- +-- TOC entry 3263 (class 2604 OID 2160701) +-- Name: usage_stat_summary id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_stat_summary ALTER COLUMN id SET DEFAULT nextval('s3billing.usage_stat_summary_id_seq'::regclass); + + +-- +-- TOC entry 3262 (class 2604 OID 2160694) +-- Name: usage_stat_total id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_stat_total ALTER COLUMN id SET DEFAULT nextval('s3billing.usage_stat_total_id_seq'::regclass); + + +-- +-- TOC entry 3267 (class 2604 OID 2160754) +-- Name: user_info id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.user_info ALTER COLUMN id SET DEFAULT nextval('s3billing.user_info_id_seq'::regclass); + + +-- +-- TOC entry 3264 (class 2604 OID 2160715) +-- Name: user_quota_bucket id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.user_quota_bucket ALTER COLUMN id SET DEFAULT nextval('s3billing.user_quota_bucket_id_seq'::regclass); + + +-- +-- TOC entry 3257 (class 2604 OID 2160664) +-- Name: zone_group id; Type: DEFAULT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.zone_group ALTER COLUMN id SET DEFAULT nextval('s3billing.zone_group_id_seq'::regclass); + + +-- +-- TOC entry 3278 (class 2606 OID 2160675) +-- Name: bucket_info bucket_info_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.bucket_info + ADD CONSTRAINT bucket_info_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3273 (class 2606 OID 2476484) +-- Name: bucket_stat bucket_stat_unique; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.bucket_stat + ADD CONSTRAINT bucket_stat_unique UNIQUE (bucket_id, placement_id, timestamp_addition); + + +-- +-- TOC entry 3298 (class 2606 OID 2160768) +-- Name: category category_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.category + ADD CONSTRAINT category_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3270 (class 2606 OID 2160640) +-- Name: goose_db_version goose_db_version_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.goose_db_version + ADD CONSTRAINT goose_db_version_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3284 (class 2606 OID 2160689) +-- Name: index_type index_type_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.index_type + ADD CONSTRAINT index_type_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3282 (class 2606 OID 2160682) +-- Name: placement placement_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.placement + ADD CONSTRAINT placement_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3290 (class 2606 OID 2476705) +-- Name: usage_bucket_by_user usage_bucket_by_user_unique; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_bucket_by_user + ADD CONSTRAINT usage_bucket_by_user_unique UNIQUE (bucketid, date_start, date_end, user_id, category_id); + + +-- +-- TOC entry 3288 (class 2606 OID 2160703) +-- Name: usage_stat_summary usage_stat_summary_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_stat_summary + ADD CONSTRAINT usage_stat_summary_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3286 (class 2606 OID 2160696) +-- Name: usage_stat_total usage_stat_total_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.usage_stat_total + ADD CONSTRAINT usage_stat_total_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3295 (class 2606 OID 2160758) +-- Name: user_info user_info_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.user_info + ADD CONSTRAINT user_info_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3292 (class 2606 OID 2160719) +-- Name: user_quota_bucket user_quota_bucket_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.user_quota_bucket + ADD CONSTRAINT user_quota_bucket_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3275 (class 2606 OID 2160666) +-- Name: zone_group zone_group_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing +-- + +ALTER TABLE ONLY s3billing.zone_group + ADD CONSTRAINT zone_group_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3276 (class 1259 OID 2474077) +-- Name: bucket_info_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX bucket_info_name_idx ON s3billing.bucket_info USING btree (name); + + +-- +-- TOC entry 3279 (class 1259 OID 2474078) +-- Name: bucket_info_placement_id_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX bucket_info_placement_id_idx ON s3billing.bucket_info USING btree (placement_id); + + +-- +-- TOC entry 3271 (class 1259 OID 2474094) +-- Name: bucket_stat_owner_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX bucket_stat_owner_idx ON s3billing.bucket_stat USING btree (owner); + + +-- +-- TOC entry 3296 (class 1259 OID 2474445) +-- Name: category_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE UNIQUE INDEX category_name_idx ON s3billing.category USING btree (name); + + +-- +-- TOC entry 3280 (class 1259 OID 2474468) +-- Name: placement_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE UNIQUE INDEX placement_name_idx ON s3billing.placement USING btree (name); + + +-- +-- TOC entry 3293 (class 1259 OID 2474438) +-- Name: user_info_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing +-- + +CREATE INDEX user_info_name_idx ON s3billing.user_info USING btree (name); + + +-- +-- TOC entry 3447 (class 0 OID 0) +-- Dependencies: 230 +-- Name: TABLE bucket_info; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.bucket_info TO grafanabilling; + + +-- +-- TOC entry 3449 (class 0 OID 0) +-- Dependencies: 226 +-- Name: TABLE bucket_stat; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.bucket_stat TO grafanabilling; + + +-- +-- TOC entry 3450 (class 0 OID 0) +-- Dependencies: 245 +-- Name: TABLE category; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.category TO grafanabilling; + + +-- +-- TOC entry 3452 (class 0 OID 0) +-- Dependencies: 225 +-- Name: TABLE goose_db_version; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.goose_db_version TO grafanabilling; + + +-- +-- TOC entry 3453 (class 0 OID 0) +-- Dependencies: 234 +-- Name: TABLE index_type; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.index_type TO grafanabilling; + + +-- +-- TOC entry 3455 (class 0 OID 0) +-- Dependencies: 232 +-- Name: TABLE placement; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.placement TO grafanabilling; + + +-- +-- TOC entry 3457 (class 0 OID 0) +-- Dependencies: 239 +-- Name: TABLE usage_bucket_by_user; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.usage_bucket_by_user TO grafanabilling; + + +-- +-- TOC entry 3458 (class 0 OID 0) +-- Dependencies: 238 +-- Name: TABLE usage_stat_summary; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.usage_stat_summary TO grafanabilling; + + +-- +-- TOC entry 3460 (class 0 OID 0) +-- Dependencies: 236 +-- Name: TABLE usage_stat_total; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.usage_stat_total TO grafanabilling; + + +-- +-- TOC entry 3462 (class 0 OID 0) +-- Dependencies: 243 +-- Name: TABLE user_info; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.user_info TO grafanabilling; + + +-- +-- TOC entry 3464 (class 0 OID 0) +-- Dependencies: 241 +-- Name: TABLE user_quota_bucket; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.user_quota_bucket TO grafanabilling; + + +-- +-- TOC entry 3466 (class 0 OID 0) +-- Dependencies: 228 +-- Name: TABLE zone_group; Type: ACL; Schema: s3billing; Owner: s3billing +-- + +GRANT SELECT ON TABLE s3billing.zone_group TO grafanabilling; + + +-- Completed on 2025-09-15 09:50:59 + +-- +-- PostgreSQL database dump complete +-- + diff --git a/research/payg-sso-full/etc/db/billing_schema_vc.sql b/research/payg-sso-full/etc/db/billing_schema_vc.sql new file mode 100644 index 0000000..2e66787 --- /dev/null +++ b/research/payg-sso-full/etc/db/billing_schema_vc.sql @@ -0,0 +1,278 @@ +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 16.0 +-- Dumped by pg_dump version 16.4 + +-- Started on 2025-09-15 09:53:16 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- TOC entry 222 (class 1259 OID 1893983) +-- Name: capacity_resource; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE TABLE ngcloud_ru.capacity_resource ( + vdc_id uuid NOT NULL, + "timestamp" timestamp with time zone NOT NULL, + cpu_allocated integer NOT NULL, + cpu_limit integer NOT NULL, + cpu_reserved integer NOT NULL, + cpu_used integer NOT NULL, + cpu_speed integer NOT NULL, + mem_allocated integer NOT NULL, + mem_limit integer NOT NULL, + mem_reserved integer NOT NULL, + mem_used integer NOT NULL +); + + +ALTER TABLE ngcloud_ru.capacity_resource OWNER TO vc_billing; + +-- +-- TOC entry 223 (class 1259 OID 1893993) +-- Name: capacity_storage; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE TABLE ngcloud_ru.capacity_storage ( + vdc_id uuid NOT NULL, + storage_profile_types_id integer NOT NULL, + "timestamp" timestamp with time zone NOT NULL, + id uuid NOT NULL, + "limit" integer NOT NULL, + used integer NOT NULL +); + + +ALTER TABLE ngcloud_ru.capacity_storage OWNER TO vc_billing; + +-- +-- TOC entry 220 (class 1259 OID 1893965) +-- Name: storage_profile_types; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE TABLE ngcloud_ru.storage_profile_types ( + id integer NOT NULL, + name character varying(255) NOT NULL +); + + +ALTER TABLE ngcloud_ru.storage_profile_types OWNER TO vc_billing; + +-- +-- TOC entry 219 (class 1259 OID 1893964) +-- Name: storage_profile_types_id_seq; Type: SEQUENCE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE SEQUENCE ngcloud_ru.storage_profile_types_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE ngcloud_ru.storage_profile_types_id_seq OWNER TO vc_billing; + +-- +-- TOC entry 3413 (class 0 OID 0) +-- Dependencies: 219 +-- Name: storage_profile_types_id_seq; Type: SEQUENCE OWNED BY; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER SEQUENCE ngcloud_ru.storage_profile_types_id_seq OWNED BY ngcloud_ru.storage_profile_types.id; + + +-- +-- TOC entry 218 (class 1259 OID 1893959) +-- Name: tenant; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE TABLE ngcloud_ru.tenant ( + id uuid NOT NULL, + name character varying(255) NOT NULL, + wzcode bigint +); + + +ALTER TABLE ngcloud_ru.tenant OWNER TO vc_billing; + +-- +-- TOC entry 221 (class 1259 OID 1893973) +-- Name: vdc; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing +-- + +CREATE TABLE ngcloud_ru.vdc ( + id uuid NOT NULL, + tenant_id uuid NOT NULL, + name character varying(255) NOT NULL +); + + +ALTER TABLE ngcloud_ru.vdc OWNER TO vc_billing; + +-- +-- TOC entry 3245 (class 2604 OID 1893968) +-- Name: storage_profile_types id; Type: DEFAULT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.storage_profile_types ALTER COLUMN id SET DEFAULT nextval('ngcloud_ru.storage_profile_types_id_seq'::regclass); + + +-- +-- TOC entry 3255 (class 2606 OID 1893987) +-- Name: capacity_resource capacity_resource_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_resource + ADD CONSTRAINT capacity_resource_pkey PRIMARY KEY (vdc_id, "timestamp"); + + +-- +-- TOC entry 3257 (class 2606 OID 1893997) +-- Name: capacity_storage capacity_storage_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_storage + ADD CONSTRAINT capacity_storage_pkey PRIMARY KEY (vdc_id, id, "timestamp"); + + +-- +-- TOC entry 3249 (class 2606 OID 1893972) +-- Name: storage_profile_types storage_profile_types_name_key; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.storage_profile_types + ADD CONSTRAINT storage_profile_types_name_key UNIQUE (name); + + +-- +-- TOC entry 3251 (class 2606 OID 1893970) +-- Name: storage_profile_types storage_profile_types_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.storage_profile_types + ADD CONSTRAINT storage_profile_types_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3247 (class 2606 OID 1893963) +-- Name: tenant tenant_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.tenant + ADD CONSTRAINT tenant_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3253 (class 2606 OID 1893977) +-- Name: vdc vdc_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.vdc + ADD CONSTRAINT vdc_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 3259 (class 2606 OID 1893988) +-- Name: capacity_resource capacity_resource_vdc_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_resource + ADD CONSTRAINT capacity_resource_vdc_id_fkey FOREIGN KEY (vdc_id) REFERENCES ngcloud_ru.vdc(id) ON DELETE CASCADE; + + +-- +-- TOC entry 3260 (class 2606 OID 1894003) +-- Name: capacity_storage capacity_storage_storage_profile_types_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_storage + ADD CONSTRAINT capacity_storage_storage_profile_types_id_fkey FOREIGN KEY (storage_profile_types_id) REFERENCES ngcloud_ru.storage_profile_types(id); + + +-- +-- TOC entry 3261 (class 2606 OID 1893998) +-- Name: capacity_storage capacity_storage_vdc_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.capacity_storage + ADD CONSTRAINT capacity_storage_vdc_id_fkey FOREIGN KEY (vdc_id) REFERENCES ngcloud_ru.vdc(id) ON DELETE CASCADE; + + +-- +-- TOC entry 3258 (class 2606 OID 1893978) +-- Name: vdc vdc_tenant_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing +-- + +ALTER TABLE ONLY ngcloud_ru.vdc + ADD CONSTRAINT vdc_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES ngcloud_ru.tenant(id); + + +-- +-- TOC entry 3410 (class 0 OID 0) +-- Dependencies: 222 +-- Name: TABLE capacity_resource; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing +-- + +GRANT SELECT ON TABLE ngcloud_ru.capacity_resource TO grafanabilling; + + +-- +-- TOC entry 3411 (class 0 OID 0) +-- Dependencies: 223 +-- Name: TABLE capacity_storage; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing +-- + +GRANT SELECT ON TABLE ngcloud_ru.capacity_storage TO grafanabilling; + + +-- +-- TOC entry 3412 (class 0 OID 0) +-- Dependencies: 220 +-- Name: TABLE storage_profile_types; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing +-- + +GRANT SELECT ON TABLE ngcloud_ru.storage_profile_types TO grafanabilling; + + +-- +-- TOC entry 3414 (class 0 OID 0) +-- Dependencies: 218 +-- Name: TABLE tenant; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing +-- + +GRANT SELECT ON TABLE ngcloud_ru.tenant TO grafanabilling; + + +-- +-- TOC entry 3415 (class 0 OID 0) +-- Dependencies: 221 +-- Name: TABLE vdc; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing +-- + +GRANT SELECT ON TABLE ngcloud_ru.vdc TO grafanabilling; + + +-- Completed on 2025-09-15 09:53:18 + +-- +-- PostgreSQL database dump complete +-- + diff --git a/research/payg-sso-full/etc/db/indexes.sql b/research/payg-sso-full/etc/db/indexes.sql new file mode 100644 index 0000000..9c589d1 --- /dev/null +++ b/research/payg-sso-full/etc/db/indexes.sql @@ -0,0 +1,9 @@ +CREATE INDEX ON ngcloud_ru.capacity_resource (timestamp); +CREATE INDEX ON ngcloud_ru.capacity_storage (timestamp); + +CREATE INDEX ON s3billing.bucket_stat (timestamp_addition); +CREATE INDEX ON s3billing.usage_bucket_by_user (time); + +CREATE INDEX ON gpu.vm (dt_load); +CREATE INDEX ON gpu.vm_power_state (ts); + diff --git a/research/payg-sso-full/etc/env.json b/research/payg-sso-full/etc/env.json new file mode 100644 index 0000000..5c3c75f --- /dev/null +++ b/research/payg-sso-full/etc/env.json @@ -0,0 +1,8 @@ +{ + "ds_rpt_class": "org.postgresql.Driver", + "ds_rpt_connectionString": "jdbc:postgresql://write.09d78921-77a7-401a-b2cb-5ca11be850a0.services.ngcloud.ru:5432/rpt", + "ds_rpt_username": "appserver", + "ds_rpt_password": "encrypted:********", + "ds_rpt_connectionLimit": "5", + "IDP_CLIENT_SECRET": "********", +} diff --git a/research/payg-sso-full/etc/set_env.cmd b/research/payg-sso-full/etc/set_env.cmd new file mode 100644 index 0000000..a799733 --- /dev/null +++ b/research/payg-sso-full/etc/set_env.cmd @@ -0,0 +1,10 @@ +REM set Windows env +setx rpt_class org.postgresql.Driver /M +setx rpt_connectionString jdbc:postgresql://write.09d78921-77a7-401a-b2cb-5ca11be850a0.services.ngcloud.ru:5432/rpt /M +setx rpt_username appserver /M +setx rpt_password encrypted:******** /M +setx rpt_connectionLimit 5 /M + +setx IDP_CLIENT_SECRET ******** /M + +pause \ No newline at end of file diff --git a/research/payg-sso-full/etc/trash/payg.cfm.bak b/research/payg-sso-full/etc/trash/payg.cfm.bak new file mode 100644 index 0000000..f203f08 --- /dev/null +++ b/research/payg-sso-full/etc/trash/payg.cfm.bak @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + + + select * from ( + values + ('Объектное хранилище S3 CEPH','Дисковое пространство: Объем хранения','paas.s3.ceph.vol-m','ГБайт',1.80,0) + ,('Объектное хранилище S3 CEPH','Исходящий трафик','paas.s3.ceph.trf-m','ГБайт',1.50,0) + ,('Объектное хранилище S3 CEPH','Запросы GET, HEAD, OPTIONS','paas.s3.ceph.get-m','10тыс.шт.',0.35,0) + ,('Объектное хранилище S3 CEPH','Запросы PUT, POST, PATCH','paas.s3.ceph.put-m','10тыс.шт.',4.50,0) + ) as + s (svc, component, code, unit, price, discount) + order by code + + + + + + select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name, + case + when vdc.name like '%-v1cl1%' then 'iaas.ngc.i29' + when vdc.name like '%-v1cl2%' then 'iaas.ngc.i31' + when vdc.name like '%-v1cl4%' then 'iaas.ngc.a28' + when vdc.name like '%-v1cl6%' then 'iaas.ngc.i28' + else '['||vdc.name||']' end as code, + sum(cpu_used/cpu_speed)/4. as core_h, + sum(mem_used)/1024/4. as gb_h + from ngcloud_ru.capacity_resource + join ngcloud_ru.vdc on capacity_resource.vdc_id=vdc.id + join ngcloud_ru.tenant on tenant.id=vdc.tenant_id + where tenant.wzcode = + AND capacity_resource.timestamp >= + AND capacity_resource.timestamp < + group by tenant.wzcode, vdc.name + order by tenant.wzcode, vdc.name; + + + + + + + + + select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource + + + + + + select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name, + case + WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29' + WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31' + WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28' + WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28' + ELSE '['||vdc.name||']' END + || CASE + WHEN storage_profile_types.name ILIKE '%-SSD%' THEN '.ssd-m' + WHEN storage_profile_types.name ILIKE '%-SAS' THEN '.sas-m' + WHEN storage_profile_types.name ILIKE '%-SATA' THEN '.sata-m' + ELSE '.['|| storage_profile_types.name ||']' END + as code, + storage_profile_types.name, -- *** это не тип, а профайл + sum("limit")/1024./4 as gb_h_limit, -- 4 потому, что сбор раз в 15 минут + sum(used)/1024./4 as gb_h_used + from ngcloud_ru.capacity_storage + join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id + join ngcloud_ru.tenant on tenant.id=vdc.tenant_id + join ngcloud_ru.storage_profile_types on capacity_storage.storage_profile_types_id=storage_profile_types.id + where tenant.wzcode = + AND capacity_storage.timestamp >= + AND capacity_storage.timestamp < + group by tenant.wzcode, vdc.name, storage_profile_types.name + order by tenant.wzcode, vdc.name, storage_profile_types.name; + + + select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage + + + + + + + + + + + select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */ + (sum(bucket_stat.usage_rgw_main_size_actual)/) as vol_B + ,ceil(sum(bucket_stat.usage_rgw_main_size_actual)//1024/1024/1024) as vol_GB + ,greatest(ceil(sum(bucket_stat.usage_rgw_main_size_actual)/ + /1024/1024/1024)- + case when bucket_stat.placement_id = 1 then 1 else 0 end, 0) as vol_GB_free_tier_subtracted /*считается не в точности так, как в функции*/ + ,case + when bucket_stat.placement_id = 1 then 'paas.s3.ceph' + when bucket_stat.placement_id = 2 then 'paas.s3.cphc' + else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code + --,bucket_stat.placement_id + ,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ + + from s3billing.bucket_stat + join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id + join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id + where bucket_stat.placement_id in (1,2) + AND bucket_stat.owner = + AND bucket_stat.timestamp_addition >= + AND bucket_stat.timestamp_addition < + group by bucket_stat.owner, bucket_stat.placement_id + order by bucket_stat.owner, bucket_stat.placement_id; + + + + + + + + + select max(timestamp_addition) as dt_load from s3billing.bucket_stat + + + +select + sum( + CASE WHEN + (category.name LIKE 'get%' + OR category.name LIKE 'head%' + OR category.name LIKE 'options%' + ) THEN ops ELSE 0 END + ) as get + ,ceil(sum( + CASE WHEN + (category.name LIKE 'get%' + OR category.name LIKE 'head%' + OR category.name LIKE 'options%' + ) THEN ops ELSE 0 END + )/10000) as get_10k + ,greatest(ceil(sum( + CASE WHEN + (category.name LIKE 'get%' + OR category.name LIKE 'head%' + OR category.name LIKE 'options%' + ) THEN ops ELSE 0 END + )/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 10 ELSE 0 END, 0 + ) as get_10k_free_tier_subtracted + + ,sum( + CASE WHEN + (category.name LIKE 'put%' + OR category.name LIKE 'post%' + OR category.name LIKE 'patch%' + OR category.name LIKE 'list%' + ) THEN ops ELSE 0 END + ) as put + ,ceil(sum( + CASE WHEN + (category.name LIKE 'put%' + OR category.name LIKE 'post%' + OR category.name LIKE 'patch%' + OR category.name LIKE 'list%' + ) THEN ops ELSE 0 END + )/10000) as put_10k + ,greatest(ceil(sum( + CASE WHEN + (category.name LIKE 'put%' + OR category.name LIKE 'post%' + OR category.name LIKE 'patch%' + OR category.name LIKE 'list%' + ) THEN ops ELSE 0 END + )/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 1 ELSE 0 END, 0 + ) as put_10k_free_tier_subtracted + + ,(sum(bytes_sent)) as bytes_sent + ,ceil(sum(bytes_sent)/1024/1024/1024) as bytes_sent_GB + ,greatest(ceil(sum(bytes_sent)/1024/1024/1024) - CASE WHEN bucket_info.placement_id = 1 THEN 100 ELSE 0 END, 0 + ) as bytes_sent_GB_free_tier_subtracted + + ,case + when bucket_info.placement_id = 1 then 'paas.s3.ceph' + when bucket_info.placement_id = 2 then 'paas.s3.cphc' + else '['|| TO_CHAR(bucket_info.placement_id,'FM9') ||']' end as code --*** зачем делать там ключ bigint + ,bucket_info.placement_id + --category.name, bucket_info.name + ,'WZ'||lpad(user_info.name, 5, '0') as wz + from s3billing.usage_bucket_by_user + join s3billing.user_info on usage_bucket_by_user.user_id=user_info.id + join s3billing.category on usage_bucket_by_user.category_id=category.id + join s3billing.bucket_info on usage_bucket_by_user.bucketid=bucket_info.id + join s3billing.placement on bucket_info.placement_id=placement.id + where 1=1 + AND user_info.name = + AND usage_bucket_by_user.time >= + AND usage_bucket_by_user.time < + group by user_info.name, bucket_info.placement_id + order by user_info.name, bucket_info.placement_id; + + + + + + + + + select max(time) as dt_load from s3billing.usage_bucket_by_user + + + + +select wz, code || '.vcpu-m' as code, core_h as raw_metric, core_h as metric, core_h as chargeable_metric from qComputing +union all +select wz, code || '.ram-m' as code, gb_h as raw_metric, gb_h as metric, gb_h as chargeable_metric from qComputing +union all +select wz, code, gb_h_used as raw_metric, gb_h_used as metric, gb_h_used as chargeable_metric from qStorage +union all +select wz, code || '.vol-m', vol_b as raw_metric, vol_gb as metric, vol_GB_free_tier_subtracted as chargeable_metric from qS3Vol +union all +select wz, code || '.get-m', get as raw_metric, get_10k as metric, get_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf +union all +select wz, code || '.put-m', put as raw_metric, put_10k as metric, put_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf +union all +select wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric, bytes_sent_gb_free_tier_subtracted as chargeable_metric from qS3OpsTrf + + + + + + + + +SELECT + + s.code + s.svc + s.component + m.chargeable_metric + s.unit + s.price*(100-s.discount)/100 as discounted_price + s.price*(100-s.discount)/100*m.chargeable_metric as charge + + + s.price + s.discount + m.raw_metric + m.metric + + + +FROM qSpec as s, qUnifiedMetric as m +WHERE m.wz= AND s.code=m.code +order by s.code + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/etc/trash/payg2.cfm.bak b/research/payg-sso-full/etc/trash/payg2.cfm.bak new file mode 100644 index 0000000..282788d --- /dev/null +++ b/research/payg-sso-full/etc/trash/payg2.cfm.bak @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + Отчет по PAYG #request.auth.wz# + + + + + + + + + + +
+Период с +по + + +
+ + + + + + + +Часов в периоде: #hours# Строк в отчете: #report.qCharge.recordCount#
+Актуальность данных: +VCD Computing: #dateFormat(report.qComputingAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qComputingAge.dt_load,'HH:MM:SS')# +VCD Storage: #dateFormat(report.qStorageAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qStorageAge.dt_load,'HH:MM:SS')# +S3 хранение: #dateFormat(report.qS3VolAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3VolAge.dt_load,'HH:MM:SS')# +S3 операции и трафик: #dateFormat(report.qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3OpsTrfAge.dt_load,'HH:MM:SS')# + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
АртикулКол-во (метрика)Ед.изм.Цена ₽ со скид., с НДССтоимость ₽ с НДС   УслугаКомпонентGPL с НДССкидка%Оплачиваемый объем
#svc#
#currentRow##code##chargeable_metric##unit##discounted_price##charge##svc##component##price##discount##metric#
Итого #svc#:#NumFmt(acc,2)#
+ + + + + + + diff --git a/research/payg-sso-full/img/Arrow-Left-icon.png b/research/payg-sso-full/img/Arrow-Left-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d7821a4fe72554a4a832ef361411e443a5e67848 GIT binary patch literal 12641 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 P00000NkvXXu0mjf%X~O* literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/Arrow-left-icon (1).png b/research/payg-sso-full/img/Arrow-left-icon (1).png new file mode 100644 index 0000000000000000000000000000000000000000..fcd2dd5033858ff4c644f70483e2c89a29c4967d GIT binary patch literal 6246 zcmY*ec{Ei2|9;QHOop)yChI6Wp{yZhQXvwO$Tk(BWXT$aK~l11S7}C(>>^7;W2Q(^ zwrp8KDOs}b>vulC|9*emd(XM&eV+S1&+B zWM|z!=wE3A0DHvb6u~-p@L$dyACbubhJ@gH^R|q%B_<%5rZhu;{*ceaGDX_H(sT3v zwa}*n<~cNz7LO<5*)OwAJl%9|y-YP1?Z2htmHP7BpxN~;Beh$z>bFE|O+*T6lsSXYOsAijC`c{sLL#Xa(i<)!gUkJXr{`H31uy|%sI2nkxt^0n>RJs8yHhXP% zU|ylty_39TjZOWU&6Lw9ps82^Gc-)7!b7$1mCViu1^L`HmJCrWZC7~F4m9uL$izv<-}T{Y4Osd{}dc=2~Z za5Wd>B)@gI+Woz7SosibT-ASmQ?Bl*GWMVdSqKA^aiDmK^krEZB@V3jj4C$JUcC)- z8_bp~rlE*n2mLjA!~~56fwA7>w+$1}nx2X7=O-f)_hrh9#S zR`FRkpdK20{O93x$?-d!TRarqYI*}VA&)3Godx%SgCTe}AwlAX*k;fBWvSTt0P2$B z>kZvu^a8C$zo`>z9@G4%7-d)kX}R@Lbj= znQe~wF#cK_oO)4Z!TU-Gf+Ya@6_`a&RI5Q`v-2;(m+R)t0|oWZBC8c^)chn?(g^B; zF^>wJl-!t8J|=*38WJo4asRr$`6W{c$*M_XLbK4u=H2Mu3!RRX7+R|<&qCVsLT;wN zKi?UdZ5;aOniwyc9a{yFb0RcvzurI%w=dD8SBuB?o}D+;wrGz!q4jw0LAGUIckfSs zZC>&jcDw|1p#jP`4JV$acif`qxkK>3wIa3a{AA1Pt4Ibbv!R%EImH}`}<+EuFIVK z0E}~86dmgy_n_c21p7ohY7YrrNa4aWITRW>A9{}m-tDi}^d^U*4Gx5RW6w5R9Qfx~ z)u)%p;ac!}?3Qz~xpin!)L12idkcP%%>NkX+OExEFV_WE&P(eijDLQj zs-c^x!Zwws4M(RhrGLxERVWw(&KXEuJW%RbztfS4Q3tPfyp;CXYpnt+UJa+lN<>$e z>N1l^+vHl#tFP^_*hX~M2B(kT`HWG?>aa1Ot&L1^#DgMfz_vk&4fDcbceWnbiBjwut~0MkxaDZs=0 zH@{5Uvr919qYdqz}#dhp&^#-3aykj~?>)E)MM=(=<7flCU zZK5cTukKX~lK14;U!j#<0cYY!lnQD0K^P^ZY(l~72$Im_?nZ!+TgwrzBN}u1OP$|| z(e#&a8z_6@DFp1!{+tf_DaM!%sq4S`^Qcwdw@})jf!rku3h^PyTa_G}PbD z>TqZbEwY+<9Ztm7C;sBe7QLH09v(0Md`dio&^o#|b{b2GU#N}YVtJIP;3y-ZwCi@g zo=?$?uWi>GH1ydq%{n#yoT$CmimD=%bOG-Y7d}D_5}goWfybdN_%A1(h&`(5^Tt9- zFsbsNV!0ld;fvh{nkvg3Q*G$?hx{7KO7b|`SHhr0t-^Lf9sgE7z-zk0JvVofPX|#3 zXbCWb^othFF!NXuh`XkkypoONjB%2l4zS)?5i zS!3?~lkFOgRqZantKGMnh*qMXLo}m-KzG2HQi=213y;6ZyJFVQC^P*%p*=|o)ySGGiT`riD79PU98GrpHC@-&=){R6-3@aN1!zJh~-2yI-TDwh& zS0Q;_24%L0Sc13Y-6j%k9#f3Lu-H_yZGc*#>EEWJe#J_V1x))P71+^8W-GFxf1iK0 zJ~4W5^rq22jH_jB0`xRRF@Eu6R^;<6?~A7>RN^&?iap}1kMAPXq7B^tBLw6T`^$Bt z#Qpsgi-TL+Nra2XxmH`gPu`R9CbsP#JZw|yzew#VwHyi&Q~1sCS7!$q#a*8me(69J zANm}{SwL<&{VU`V?9`t9X->TRTNlX3C01VqIc`^;AhZjqY5917H@#1X5-OvRx#Hjv!b1wXLR&$^YxVvDm#AB zHp`_ncJ5yjoLa`>N!VlHUR=K+)h5qo@rLn6s0!^KpZAf667diVrZlMlo3Gh(Y@Y?= zadd=)E1~n(AU%Yqf2z%yf@vxl<~AV} zZiH)SNKkg`WHG@Ck<^SJh}nVrmDP`qBk-+E+2%HRjdTGGpUP!kIj#)Tq9nulfzx$* z8#218YF$Z-(fY}1i<=MP0^KoQocDpUKezOc8~)sUNQLH`(2s}sE5YI>_zx$wk z?kjf_a%r7$!!UAdL82a8=u+$VoG0Ax*UrV}M+mw_>rTuYz4WTY97)b03@=1n=Gyr} z3SY8P^+7D@Guf`37nnIAwP*7h()qrU!kU>U!Bzr2weR5brFrO41cerg)6VJi`>SvJ zmJ_yLH_+Ml@IvBKnmwhUfjxsjH14>QQ3u%!o&~`S9(YW(W=B3 z@0evJ><4E#ZBWIA;a-kK1;#w!1hiLRHD!r~BrNj%Ny7QIR-tnSv5W!4LZQ~pg`D(rHBP)=RV-YPPV$utp17L}1tKU|e$ zwD5xDvO9eM|67ImGnCrO9PO+TK+o#LM5d<7XK>AN(jla4nOXY})NWGoz$z!3P4#h) zNy{Ya`jMee^KFax8$3(vhsQ|nYd`4Os}@9!~C7?lZw9}DU?ZqL=X|j^>9H-0g#Q%baKhQUc~)dI*e#{6j2o`@2EJj$ zQ&KfOA*gS|6J|$cuN#f!{D}B)+jxe(r;NbQzaVkmbuGt(oIJ?qGR;wkv@*ljW+|TX zkh9An0V$+ALH75Twi8h&bajYrG}x?0VS3-vg(RZSQZ&4|#kvnKhHx1ijCr#z?Z;NQ zUKm5W?{6wBJyhqD_vk9vY109G@U&{v@AdX~MvD3ZwHqeY>)fHnH%25l_Z<>ZS-Qp* zP|LvN2c^!T<6m3mQ(;s~mrBw>DE_1uF5a=}q=>v{+7X8J+JD?wWO;S1Svp;^v-|3B z(u8UyzL6{aLukwSTGG`nDAhK~`j3<9Qp*7#wY>foM!tKU$MDB{VYx$qfh7yWsX^`F z6@CLFxRNG)nIDKJ356sMqfBp1$qZd>GSF88-lKbxW~X8Ud?Wv|_slGDOV7#n(my%?}cP-V2KJR?R{pVw^ zVB0tdzP{!>aI-2-&cUgMf@BLFk&*IOJb8uwTz<{|K|N1lI6^1qPY321r`qeim$fUF z;dM{N3;QLa+gOvey309=4=j~Yb(O z3yJifQI87ki4AC+2K=QBGo_4ryu#Gq#}gB-sf{8RGCo7d=bRd>Rq z%!Lv7@-JuY_je$^tnzj3=dJ|O>g6Y}cco+CK*&RSQHv1rSjaKjkaZpjZ4=z&x&E9V z$(&Ku{Koxp6HM7f_uPaeV7xhvYVLx(Ng+$Cvt`O#DV1yQVJrfv!Q`LN%{yTt{oeQ9 z*@q0!!YqIKcr2XzD^idAc#vRI5}CcJwY*q3{;5U|7hD;>nfaWJDkykF9T?}u>RWK< zKJ3@fREm6on2#l2n${U-jwU*g6%89fc-wlDl*L2ESkC8n{IrOC4u7;$WRVV7tlP~5 zW=eNppF0O1;CrDPeedKI?XFGGlcoi6KCB+)%iP}GXTHozxbVK)R{O@l`wRG#7@#V4 zMePt00+B=;yRJoKq?Ngj<|D36gI9*Y>)?K%IGjMWG!#DJQhbDsKrV|8`Y?T+zU2^) zQs&&bJ0hc5mBqM>I{$}#NpiNty&dNGf{}8uM53j;vO0xL&gVZhJT{=#QM3DRjl2;F z9Jyny=YgnLga0zqGQ{ z9wz+M&hD+@wC30My+iYi1d&TP;e;bd;Iv&n&-@Y}W|Z+BK|U371DXFqW05v8q(f}^ zsLUDHM3fW%P)FPlQq{YoXgNh2PbF+D^Ub9VreX1eysH3&vPXoWn#xSGoQ7u7fzlHk7;#w ztEn0TxT9y!7Rr_13#C!WOFl;yLJ>*kKhE4-FcsX8k{jXSJOPHVfEPZ-#zvm0Bk4rX z{QhJ`(%cssiCW!8GF)f|);v+T&Z=P~T(kVFherWTJm$~Gz~eUx?4Ngil5}m7`3V2h z$N1{N&|EV(g<8Pue_sw}_DyULPnvQFvs9Ru2CFw`)T|m!c=1R-a}Wzh9s0J*el(JZ zyoY4i@cfqrO+3l@4ls|g()n*nhwu6_KPUy{1POSbRz5j8Ai)2v{GVj!$R~SVFbDMn z91ig*Rz->;V_&)os7lss4H5==y{LYpA0}q{UCr=Az~1w}5Naw;U%q)}@k91A*(-J< z!kZAjZ&)D*v5<$ZN>7^M6VS_wH5K#m=QuxPrWeEx0SpZXPfI^*`02LQ*-82~(R5q# zjwt1sO!%!0vBkn`2Ts5dby)C38l36jPO5>(v9n11K0rs&*7d)nSZ(Mu3_WU7)%F#` zNwP06<66HyM-c@X?9{(aa`O4PH3#SZg|ojWNQVZw6mfec(q*4j45RSi6O=jtFmL~+ zT0!@Ch9hR}+)F&tWrN)t#s)v#sc|xg;2k1Vb&lR8P{m-FYSyw(Y@!A$a-Nr~oNM4+ z!I)6we5KoTGRnPhplSLR5WH`kl$T$S_Sr<15V#Jekpb9W7$cU5G157 zn)H#K2zg*>)!O~>qEF3?9g?jzFEvmVoD^St$Hjp1v#MoL!6~k{D5`FKs@+N z9tJV|ZPR3+;&$yHKUUyr%c?-2_grM6*yKb(_IIG<^C-p2sk!t?f2l1^yxm_P25}x> zCmy|@mbPS6N6P3=zgKMQz_Sp`+T%kUa%Bt^0`9GtU6U34;fLPaG#Z_dU`4ZkucoCv z=My0}Z0}jD+?Do#3w7wX8oX8)kR$Q z@kwhAv;2kNxc)`;_1|WdY~)8vC4C3er+TtUGWL@P&s(~^+zEaha3;T(7B4-5dU5Ib zUVuV=2V0!KWOmz~qGkm!rEtmlWs%wtWqR49`D`NX(e2WPTAE7lP2+14dBHi;!=)R+ z#c?&Xj_DcyHR({w${}0J+cK&yTVlq)s_h&r`>$U;J?>}eDKoFOYi@;I5t4Ca;U|0U zm=}!#RfKf<(qs|CfBM+Pji(W^j^H+gpiDMdbyP!I$)6ZHdvx2YERBL8n+YTr&$G~{ z11h`CHbamr_^kBhTWgbB@3N+=^KllWQESCgg-pnmmuK5;RB)Gkvfe#w(^tc(r_9Az zI=iFKXhvxi$DMom*M*})5Nxgcq5}LN(!JrN;yy*a{4c-XV|OJ;ib9-gA|$5>rMFhW zI+G%`wiJ1uEt)l1>gMJ_(;Dz;V!ecRz<6;C~TIc?ASje+_wgv;Y7A literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/DataLime.svg b/research/payg-sso-full/img/DataLime.svg new file mode 100644 index 0000000..8686414 --- /dev/null +++ b/research/payg-sso-full/img/DataLime.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/research/payg-sso-full/img/Knob-Left-icon.png b/research/payg-sso-full/img/Knob-Left-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5b6129fdc0f019871ffd2b900593bbc3993a6580 GIT binary patch literal 1722 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 JGmw}1{{ucceMbNQ literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/add.gif b/research/payg-sso-full/img/add.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8c5d3fd97a1d13fae0f4c69760fa33ded4612fc GIT binary patch literal 69 zcmZ?wbhEHb-Da(-jb~)A1_1RD5rhB$ literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/alarm-arrow-left-icon.png b/research/payg-sso-full/img/alarm-arrow-left-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..61a0d0460487adc02c399856b7b28a095634dbc2 GIT binary patch literal 24085 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 Yzl#E>QsI8RXB$J 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 literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/arr_dn.png b/research/payg-sso-full/img/arr_dn.png new file mode 100644 index 0000000000000000000000000000000000000000..e7a4ca5a4dd66f30355e6cbea2e18ad52250c1ec GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k&H|6fVg?31We{epSZZGe6io1R zaSW-rm7I|9sQKY`1i}TSZW}nOT8v9s|D7Dz=@*TOpAYx9MV7o9ggRRlBwalrP RjDU7Ac)I$ztaD0e0swYTHzWW6 literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/arr_dn1.png b/research/payg-sso-full/img/arr_dn1.png new file mode 100644 index 0000000000000000000000000000000000000000..75389bb6c705a69f632eb516122417fb23c70ca4 GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k&H|6fVg?31We{epSZZGe6pZ(D zaSW-rmHgxXe|u(4iRmobBEoAEML~qUNN~8bhQRFPiwS&F4`0|I+OeNuqv<5J>=ie} za->)qf5-^bGdyY!_`|5B)^VEOz}KLFv%{66GD@anz2ioUvr2sGYz$9U9Gw$dmdgUP Oiow&>&t;ucLK6T9WHS~3 literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/arr_dn2.png b/research/payg-sso-full/img/arr_dn2.png new file mode 100644 index 0000000000000000000000000000000000000000..2cf29e7092e71c8b565a8431e8b3994854c66bf1 GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k&H|6fVg?31We{epSZZGe6pZ(D zaSW-rm8_wqm88J>cv3=Z(jwC}O+eyJd(x{c4%Vb%9jP-5izKABF?|$Q*yeUAfmif) zlW((vzgTe~DWM4fY7sPG literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/arr_up.png b/research/payg-sso-full/img/arr_up.png new file mode 100644 index 0000000000000000000000000000000000000000..44d92f22f13c7b094639cfe0fb6dd920c5221be3 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k&H|6fVg?31We{epSZZGe6ioAU zaSW-rm7I|9 zd<15hx YcIdLTY7$Fboy85}Sb4q9e09^++_5c6? literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/arr_up1.png b/research/payg-sso-full/img/arr_up1.png new file mode 100644 index 0000000000000000000000000000000000000000..cfa15b8134ddb89af8fb60b0b2d15cdacfea0c89 GIT binary patch literal 179 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k&H|6fVg?31We{epSZZGe6ioGW zaSW-rmHgxXe|u(4iRmobBEm}@WjfY7ZnRM3ZE~o2XU`PFlq47bP0l+XkK94$3$ literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/arr_up2.png b/research/payg-sso-full/img/arr_up2.png new file mode 100644 index 0000000000000000000000000000000000000000..56989ed084979f0643a7745b83409f1e00797df5 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k&H|6fVg?31We{epSZZGe6ioAU zaSW-rm8_wqm88J>cv3=Z(jt=%=8vWtV(LpA1v<_%eyrEn$8tnzhsgnvdWJ{s0e={^ z)H-|*hbjDHI&#fnk9^nKg-OvHGC5e2iZ!H{H8N_6d1*|UU@9QGMkPCf_2`yPi#-wy YyG*Xnotf*r1ZX3Jr>mdKI;Vst0NQ#tqW}N^ literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/arrow-left-icon (2).png b/research/payg-sso-full/img/arrow-left-icon (2).png new file mode 100644 index 0000000000000000000000000000000000000000..2442d24709681973fa6bb21f24984d08133cf23b GIT binary patch literal 1388 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 Qn{9CTfYtu0eQt682SdLMu>b%7 literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/component.svg b/research/payg-sso-full/img/component.svg new file mode 100644 index 0000000..d8bfe46 --- /dev/null +++ b/research/payg-sso-full/img/component.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/research/payg-sso-full/img/deer.bk.png b/research/payg-sso-full/img/deer.bk.png new file mode 100644 index 0000000000000000000000000000000000000000..85ddfaecec9815ffb94f6aaab95586c19fa30b8e GIT binary patch literal 46591 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 Eb08U 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 literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/deer.png b/research/payg-sso-full/img/deer.png new file mode 100644 index 0000000000000000000000000000000000000000..5605a88d26a42f8340661d52d2b5ef1b59148349 GIT binary patch literal 30505 zcmYg&cRbbK|M+boTei#;A}fXLt)x&!HYt>y?Q)5X5E`P4Yb51bCEKO!d6AiGkIZXx zw15_kKZ3Xdi1(yJoi4m)W54uL&-r2gTZKS-PE`TgPqaUyia548{w)rJ-u*H?lJJ1a3ZnUZ0wO%i|Eo=x8gyS{ZaC3Jgom|>HIw;!Ca0sC!NZ~> zd@#QJhzF)px9j9&TUWN9yff*4LMvSG1Z?5<_W)^&G(r)wqT283HQz&_Xqf70SZq4XNZO(AK|8lfg zq?6~EX0OR|A5Lh5>G-QQzdw4}V|2nzaUd@1`!S?SOKlyN+6L$YPgN2)HGy^BUkO4w zR_BiQ=s4WAC^z_F;;;Q5zJ$_(!fc`R$NeK{!DEu%XL5+8!bNS9Kf zKLN9w<2lb7z}7^}{Ex6Gjo?+esA(^`Zg$=%Sje~UC4*y)l_^w$Y6=~#o@5Y3omY&; z*8&p1m=e|KNjwrsQ-4r>HcM+WnwP{KtLaJ&nJU?&h3c-DW6;)dLxc6@=ULS_lhT@o z+%6VzpV#nZ(TgCOnI5D4ka|q7K0C~CMh9axHMNc9*#GtE|oMT-RS}+tMa8u=u(e0E1+x zs=~;1_a$@cPNGz%5&DDKr*?A{i_OjTkfs~@S8%bZj5zR@wv=tK$Bpsj% zvVP~9pX#9^qIkL&s~ix#GV~s;3@J}S))y|NwxvHvjgI>1uRZyQ@uBd=O$K%5EH~-T zmg}1j=q(Y`+$HD7c_8li0acw^KDA1yR8nTIosFp8YyXLQjAG3m4(X^MZ{2MIY_Vt)QtqQ>`n3H))9_!>wMII|p=dxWA< za)i>H1TFfeOsaIZLq?6YLqAH}%_=-OAW`e(=vBc?E5zTQ2`|YDrBOri=m(YxHUVQZ z?I;Hloamz&=C;{0Yji+|6M&_-S0Rn>OHB9svTQYn<`;iZPRsUty#la_bpN5v6?t&1 zP`cKfZ`vtyB=tu&9m(XwwFGsGx+`hQSEG!R^r|Q4zVYr)YOloyvv^}X} zSed4&`T*THQodKkcU^bx!2y=-x$6R*emn2SqpH>srzk$UC+|!M?Nf zGkj!CBMqML>Gs?F{sr!=VUqo;oKiZ~te&`{xt)1s)$QK+aUKz4dIk-c1Us!9VgA>h zIdK+=X#4s=9Rn};)C;O{>c-y14c)K3R9W%C+lNv2De16rX8{h)t-A~j>ny%qdrch4!&5-J#@Z!47|Q!_L+wq` zStEh-AdP$F(6ZnekOd^ zM)k*PsLW#z-F?-_MV8>l%iYTUqaNNJPC&gwzD-PTKN&i)G4$Ij(=|EXuD+;SkA_}j zmEo3R)Eg68|H34-Z%15#yKh@YhY@{*Q@|&@%}7do542g$axF`7#Q$s_S(BZ(xw$)^j(;E~*c0SP2!O%Z8qdWb6P>9afPy|aZo8eCRRt+?wH z3pYN+@o_+$wgSKSgd|P6oz}Zp)_ioMM(SOYcb6?93v@WoYgGGMu76&cNMWTzlZzHi zwm3QAH%tH4{)h10>+t9NzAFK} z8GJeQNvU~&#OaH1mho?=ep6+kl>IyLSml@@CV(5`qoQY(^It0ZUS@TB*15;x;oICA zC1QT}S<3I*vuB*w3nT*5o%=ng#1su^V$Sh=(GO@TuVq?YG@gUSgJ3Z}&(suyv*Pis zq1gSHD^hrxYd5fEl6!l(n`eEeFPV(hL=JgSRnBtPFBs^d&F{v6bf+Lrzmc0(9Xr#K zu6xUhQMK;BQkI;Gy=UR`gaRbZL0~txgi5v*LV%jPza&!k!WI8`($;Oy$tMRLLF26P zGVq#sq4Zy~J9qI`h1uzAeiZ9A*1=mpiwNCaF_%yG(uB!CmZu@6VMNWLTEEEP9lla@ zxx*oVDl1L7a`=uncDjonx#kzO%4;q{M^)%&ZD1Tf7Gw`lOV;0+ol6fBx*O23RoquJ zmVrXS3^Qb6zCrT=3m6}BZcXT)jk1{@%_piIcYj{qLjnDXN z&Aj;1JR`*C<(9>st}El>JdgKlT0A3Zkv8~^5LGXH0`JJSk}Ca)pQovUMepD_HT|2k z`29T zMsx-l@JX@>-Ve-Kf`e8(l_#TC+@EjKeyC!>^R-FL(f=VP6e^9l% zntb~$TN2SQ&R@hyI1m?2<5<|UmVd-7;o8Uf2nOOKG%~PDws~wBXf=$x@SICH&^Sfy zUI|*|SLR<`JM~^QPJNrnPk~pgQu|qBKn&KP?PlWk;#$}~GKCdw0?Efru;$U1dEOCG z?=r5(0k(g-&>~OLOd1$e4H3J;^GEw3Z?SP^XJhZL?!O|!$(_$$|HuV&=AcnoT5OwB zlW6tj^S7t&DyjZlQrNP8UM58iyo`r&``kc)YHM9f_W$rT$RPd_fq90dSM1dUWY0^E z&JC3C-F@D%wBbdNB~wI2c&*Ni6cy|e<@(r5EZNTXdygWk2>H0D z$GgP2zEgKj$m?1JE&U|~&y($S5>Z4>hajFItGNdCx>aYv05~>|m8Zit5^o>0b{@zH zo2@o6=Wt!rsVLm5!MW0N+`w1Fu+G;b<(sTMy4o|tejgz^&3;e2*?7lT&zewN@|M~V z^29BTt;P#J-hW?LHofJGYrVTH$ysW)UV)_&9GUPPJLB41#pNp5`l|w%$CejsW5;gXx{h)zxL^Q- zeoU^7HCkhb(5w-!wqX9Z@$`;d15K6H>*2lZ7%bldYo)%q-6lHn0L5vz(5rtgAXfW# z-PLpR6f_(pMNhWJ^#{c+-6`*T_dt77deBw=pV3EzRvy zQ>A5ra$fjDQyO17cItC$;hO;$KqMj7@QHKK1hdVg;lc3$B`wpV=}@x2*fSloI*NO? zX_LKK{oLv;up99=<{kHji>&pmWFKP3ZXe$ce}$Xat5{SD`u08fRaR09aN55{HjQk4DQ&uXZEk~OOCHR(9zEdkep z&3$UOoMOVpauGF4!yJ;Q`lNrqblX}v!e=2^e&WN6ip8KXAb#IXzumG+6tY_3_O?S8 z==q=S4HzmSWZ>zWGUN`|hpNdD@qTxEI~hbw!Ya&R`-X0>P8+`Q^y(BEv!ve! zCj;uT4R>qFNjG^JkhZ`~=OZeLRN7r`rm`+-TW{oJAFCM;7Nt@8y|a^CwL-0o;$Gyo{LhY?5&d)ud3h*pbtW&kroZPENaddgBB$s<=IT@eb zEgCRLI0J2%2mYKeTDHCUJosxoYyKGG6*jGIx2XCj*LST=GuF&~)u%u9h7?#Hp};T^4bWL!EtvlTinPmR_cvQ%R|cM}>kcb0ae6v&`>+@<`@} z>64lc>{WU0XBA>=?*wU#kjmF&jt;Kbz%; zG%eW=$5R5SX}t?dq$fzo8xR8`8Rij73*uUP8;OCFjHuqT`*8`3azxU zW4ZRsz2WUrTg>=*aJx-lSnHDhM!CvhNB0hq<2ni%S*g@gMzkl2-o4 zik2kXV&miLUSC{v{-Q*uGKQ*|@P9=xXAe+9=&8N{7dOj9EzLOy?1jpVTFLhMbJtoS zUA0>}d(va--dEKn38phLMe=QLAu0!39@YQx@0*3J&gs*=I83Fq2qSz7o7Y8r^m`m{ zt`}+S!q+$d$&`4dPxMuo?wb_1788a1fjSvLT!~#(Lp{WeUe?-3n(I;I8Pactq~NZ# ze=2(VmO*_$-it@wX^KY?LDZHu>3%V|YAH#AO*v}SyUe!W&UTYqYaCuQd;>l9Wv zqQI=QsppPk7hdt!>U_{x_G!qawegyn$tAWewFr%frkx*=-2@3)5RL4=I(`9klTl{# zZc3U9LJ_HaT_$mHPzB;BUzm`U3S5ats~vAZ2&a0NI z@%H#BNF+{|`(7%d4pbfOYW(hJtyADt$arc49!D6=v)|dWE9-LE^`q6l(f^ipUykYe z?Tww49fuRZK{e0T6LHU*ui&K}Cl}Q*;=Q%W$HQO~HrD(~?<5PDJeXufY`Dm!)Xly_w6zN);0u?K$$~6nE5cXFZm;nKF z1L@I2`0&jky44d)Q*h$c&mzY1@Fuux^P)e_K74+|#na>7M4gQIq2s#7xIIrqf)VK| zudXzasp{P`&uWTY2Uyg7RJVVr@F&6dKjcY8A_`najB1eih&M`^IC9LH9G`A0Ht`pHw1rmUm{b{b2vE4~AazA7O>R2iz6gQqZ@s(($BJ<{Gaqru;vS81Jp%}Z$8Gp^} zLyqQkk&zR5WBI#HgrtM>8o(~xn1DZ9Y^55i#5^?!5V_p7lpAEN(ej*{*jT^BFu%0D zbv=f)v|L-@#o;#(zDBSMs}5NceLbs{eewM#`7BLRkN45Zaj4rwmp=Kxe&5vMvS4NQ zMXK$;7$hZ+nstF*x%z?>3DD@Wv8SkIDaXI^D9yFVU!e<6k5moO-1|g!8Dk9RH=XUs z*R}dQkKXwYKF#qAio60zu&jZX^5UWmh8(4d3Mw3|nZP&g@QN716MaD>TaAm^?WN6% zr(#tbxJzNl08!EAz&JW9C+9xj-PmRS7^}SxwSsRzJ;63%;dY#C$dAgcme*)M<)=0O ziklidc?vH?lNdK{ux(Siu;}w8-#cjIyoud@Wlx-44!QNMz4cbOg_h43H5W-dy_vN? zy;?RxnFZWKuQ_F{$URy)Y%01h!Fg0V)X*6iJd^1=c<;~Ppy?mE1MZyOnnmSWd#M|* z#%jkAipy=c?IdeCfkdvapM*;VR(oW|mpqQM66JU_yX%X)d3(m8+FCAn_U3{?P}inx z^7X>q(ma_L^x!TwV2CKJi}dh;uLJwhnme;5r?_T6Gtv3y6jSt zW|Wy!KnZ+Dh(~ig%!%0trPszP#U0=~&JUhg=TDd_-00EtQ}pLcj9HsmeI3oZ zpS{CT;A>nKaYM1tD2-VS%AD_I0atW%cU%T1^G4=gB}KgL_1MHOQ#H~ZnG<}>#C*!@ zZ%mHwxfPq02wY~mDzMn%iBua}oBQ8Hc(d0(f+BaO!l$86gQmt7~`2&ADza#0YXx1_nQ_HVQ>gh;$hh+L6mT*O^wZMUhWnFb?p4OG$uu=4#NP z?gu&@1;xd(sSPT9sRt};k(JUi-ktbr!!JUPh6q;szu#jr&5vOvYV>wVD8C?>f{Z*j zAQLfacjz;tW?P?;UgPEbljZ_ct4MbGGg$QHL(v zW5tW2&qwg6=eUn94X7~A=0oxVyUO{!7%n~#^ADtBwsppLi5HX#<+$pu?sQ0uvYAm1 z{I2Z$yxo*2xMl!d`X1=5>97YjJ_g&oxj#-GIXkA`zF?6{E@{Z34uxYYYy2N?`H${m zKUlQ3sNanzjDzgI!TrKB=_{g-J=5=_4^jyvW;ak}iQlVEj(1}LLFu<|BX(ZzMW znhDq54BZc=-f(Ibbumqq?9WFCM?gH=JJUO7D7L!h-R$BZFA$Iu^VJnJJJOcyz6jQ} zKk`%K)Em#YVkTj%;4Oub>josj;-)*1MMJsw{W(2k)ny`o?ea%hq5^JHlR`SWtl3vy zWgSLGse5M*LAttvqxv*SVp6zdqf+$F7!X3#j2TGu=T5kO~)rS_Os zJHkbDn@9b8X3F|f3#d@++L<5Up7ljgJV(NE^^Zhq%YI-I$|(3Ov8hK#(Cm9uW-zFA zw)9l7orFBQa8!GDZn34SY{LnTwxa3)1!C$VBi%dEqV%qd5!3C)gQo0J;2%&aL5tsUnIHDP)~?z@EtiBakT4T!|AEd5%}%{? zI$i(mMum!C2N8vTZlp}7lT1*fB#mufg+xd#)tWy?gY_>DjnzhM&zU$!5R=z-Dw;&& zstX0hBlf7vniW@l2>#Bi77Qe28uaF2cDZ1|6Umsl>0prt=5$2UFvsA62P71i|DbBd zj(jR{<r9DRYfqjMN_Q;MlMv?nGe@NfyGuKZ2i^i5i!;vQ#mA@ zzR5`V$Ok&i&-r{clC#QX^|fDcuWX#5((1fYVD)H=zaneez*h@9A%9JXydfUdN%qUb zLeYJV&A9Z}uM(w#(#qcsp^ZFp#Jbt?1jVCB2-lt>13|>pFkE|Dx@6;@zll8KPQZj1 zzGM_}2()&uNq^6jq{PjN(Sr@vxBDzDIFBx@47KwIJ?CuE#50n4taw|+SEe5bC$R6DpL;?EsBXT|d;X4X$!x5%~_6k>)X7Vzo0s&%;mhUd9W%dwlsHy*>Mo{-T3%v5t+i;a(G1;Lj9M_`VdRQ{^o~5<2xX4 z<@fEa`Qeopk9#J?S9f!4g)>4fpKTu-pb+*{okW7Oaan+lm0SufmI@P=3V-6ll_Ps! zqQlcq@fBib1G?|aH%Bn5(-|M?kkp|kZ+t2Cqtfby03U?#iji1+qox-p&p4rVF-g5P zes5F%p-_bN=+#9u9mo^@@kQG=pvAI;;=TcKWky^uRrLQhukVN(@7i(5OG0)iM95)z zoTx}AulI?XBYkNdaEPm>9&XLbt2H@-O{Xlj5Sq!WUi>R>Y5(BW)2Qi2~aCSiI@Ja^kEXE!PVCwanCd%s zKT0x1S}=KV%0W8&smaA1t<`I$K<#yNeqy`C(iKz*DkB@L=IFkX^;*qYN9sT+>Lx<2S?LW@W42W(S|@X;&2i`|XUAB#Pi4T~AGOpJCOgSj zyiYF{#qdF7Sr_|jqW*Zt!WvsOJy^ZX-J)fUo%<+{oaLtPT4Md$*b{bwYkcX zp;(SYKkv$W%nrLo`Lp;aMA<&^(X#bsC>vzMXE`(nuxaXd;pk-R)!4b!U~hg`__EAJ zvugY^x|e?TJ-m`XN&}=D2?;giP*z$wLFb8>OC!o;%)?Bx-z;#i#4a)=#8HDskXYEKVR4iV5XVU$bRb#;X$(=Sv z(k}*#Ye6r~2REs+(n>w~x{<*>Ey4Wrm;Is91TwQrA8@(>9U@VyNtk&SCPHcHbDkq~ zYNQ%z_&{GF#=%DkDHVNKrj%w!pGb~4xP3d9gqltN^|FcfOHs9B6$wuIqZYD~-_`jb zC_jBkuaVg1jqY3BJov!MqDQm+?=9!?c{e?&{tz#MIhua`Fd;;pLh#>;da2f#qD0JD zXcpqPjFHv3laE?R;56eq=h>!mCb3t+Oq)89= z){yW5iKGp*#?ar-^#~XK@-JVKkn9psV#mOM@<<1Q+7}hTU&pJ1xY1)*l!QDcs7I;E zp2QY!^aOtqvgmb<+yna3uy(>}C=e*a{*|up3TOO4X29<+TE{zr@ch|wcsyD%EG^R- zB&*yZD!eOP$0HGC#YzHfV_X_f&<$Gvvnm`sTRwP!*xRl&i7I0(ol`k|= z0iHj3_ivJ>U79UX(i1l{uA_LLt_Ggl+^-~qkD45_^IX5q{P*){G%>}Z{=zuVb$xoH zI(ia-FNdX*YTlUA4|H_TGHIBHTk(w)x%kv-EAAOZ9bpOd5F>`lDo?DH-)IMAl)paT zg6%@i2JFm+CyZ?c@pmfi4ud(OP$DyGq95(Ox_EiokHbZxV0|67=3n+2erMkc z8i9e1?kKASURxmhiD$uxg&6BTNK(i-(Zsv<@zt+u0)FD*=JZh1zPUM@r};Fy92Jb2 zQ&Xn(Vw?2{uG=xRk0)e=+0C%j5l5nhpjc!UM5~dpT5ffT9h!)efS`;P^barL5*KH^ zaqVld6p;A2cWUl~p%!W_H)SMN6TulLF}yUWYadUvj?8bJ^G+58Z2IXQJ{#U2Ce&>d z?(sbUhgDX2!!!6#%Zs`gJZW?d=E zNt@d1pS3EK54ARc*5fA*jiH$v@&njP%gGkzyywjkLxWOP@s7BjHNxY?8d4Y)+uxkO_?%B;YR@Wgm^C1t%ESLobtI)MS2PHwzGw26$pS_J{RQF)sGUVS;{h?M3(!jL+B^OgYF@b|OW)pgXdX_)y^L3&O;U87gkr;E z(dc#$$KR*RQs}-EjS|&_caG`)j6s=?L*4%n&IplC@pN6qsOcNpT}!%bhutOIuHvZ+ z%aSceu61P}_w5RkkjoFhG)Vn-mPF{hlvf3h2Ig=jzCBy3!Jb97^uz)?st zZ6#BbbYx^T^4l>7pnh7*vleEQHD}1<2|6ocNRTA}djzXwdt@{xB+`+Kef~{yg^Gw_ z!yR^C)bS;ll}An@N?j{XLhQ?hzkDx;E&Cpo6|mWnX}vJ?Hi>|!k@=gehLT2(*tr@j z;}F}vJD>kgtb7Di`_IOXRjZ?WKs`fp@?A~teRxg5lCvx7K4g>whM(^4z~=vPJ_c%U zPmbJ`Z=Dnxx*uC%?2@^>CSUG%k0i;@&KK*WneFFG*o%v60|gpo*)Z=bty%tF$&pno zOd7bhrVdd)j;!+NuPoGg9xr;g*WJ_fM|mtY=Uua+BBAsRGsK*q3)ByWIURM(8L}3@ z2u9B4gT4oso*KE~uO)WFN!ncknl~TP?rbB4%xM3dF_5!sobl|*$GrHJ-m#k7=~9Yh zT_g2EPCW9K?&Zg_YZ-iuCsx0TIi=W)ZkM+VE_%9{N|H<_yX8@x2$+{P(u6W?K2H^+`NXr0^XyL^dCE?&tUhR`X2H}mL$|7WnwR=H!O|Na3yOBK8 z6LE#xn&5;#_*c7RTdG5%BjuOZHShiDH9b&RgiFw*&;v`Qw6+;6>L7Ez#dvAz8}L^@ zj-hw^S#RthJSvg3uzZ)vg_?=XlqSqiLab)A!;VVkZ#9p#mAJA<6eKyCpzOe4e^nu6 z!DGUinne?>adQo&k))32s~qVY0+Bx@Ni7U^u1bog35~4Wpa=2k2X5hNh>^@Cg{yUW z;|q&UGH-x&1~QgWVLq>8dn23RNxO+_4o}Y(8V`H7GZWoFS5-Om6(s81VGA@QBO$au zSSioWGrT|hM**$Ti*R`&6p#8IAl7&`Fj6`087M8_E4bEzj@KfXx?X_5UOgs@T;!^y z>wQ!g4bG!!il%GHVQOQF5tsqi10@=Wp`snYZ_x3v3oKS#+(abkACsye6+aKwAw8|Bw|U3XO0CFez4*e=#yY zxMg_ljWw%M)U+Lb9Ew3>7^a=wiV!*KTR_$k@i+h#*3oQ9Rv^X|KDWgTzxVJZl(d;eMRYSeT;+I}aG zWTtd|m=f!Umirj1?`^Mj#o#3NE!ZIMDIgOq-Jp!Mm1x5=H6?!ciz>jAnp0}oz;xsa zAoeW^yu`rNF(m=d=mD`HIbUexoF-k<qpes} zBa{6D2fi4yXhX+(^baHW0XNR6YJ*6Bpc0>#Uc&}TWAdlir+-xWH5;G;q<%b&;k&!J zMJn*bW}w@#wpvUyE1;fK{5?<(%p`|{65B$)1PFF~$|e<~zQki0yi2+Cw@y+5o1&jD zRCOgfLa4C4DKS^}WU$};V2l$4%zSEEjleQtp1$#zf>^B(!FjPL5{v;j8o5OtWG(1D zv}?>4M}mHTxpNWJsmWe$D|tRmytFf$gF#i`41F&@FNE$z)V+Jb015pV zTfpz>hTiTpoI&ZUPH~?ZJOf+y^6GTkUEQ^z_oOvK`x0UC0kyxB;=Em*j|6@^_55J5 z-VDD7Mq8p{B-xtj$t8fAQ}9D5_w(-CWNdVSLQC2}h~G`eJiL@k-DTnC#?EZ~t-TMJ z2Wz06`y6UsMQ554J)g4H#+MCV_dS$dr`ZM7DtEVyPZ?}8F5X9@HN$a>N!Ya{kyUvx zd=2wI)4QW9=C}4k+;7I`tLmyeR9%WZ>k)(y4lGq7x-%~lF`31OLD1YyXA>bL!bAL) zLQjdoo~545NK4H0GObhEgDtx3s@FAOp0fMZjutrd&%Z)0k%k)N#lq7-+j-#PZ3q{X z=h{oz$zI`m3e>y5gnz>`jZ#=|0*dp78)f+_Yf_o0n|g{5G_P)&LrPxb?TYpkkEePpa3f*bt07?Xpn>_5_w$Q@9xq4ahH5Fi zY^jgf@kHPeBIo(Kk{<~|s%7*0Jm(4~`;;BetNmIe#YM={O$=7fNletPd!C@yPJt^V z#NBXagT5z#!lRg9W>Le#ndCLR`awhJ#3e|CY$sf-yk1j%rEwglzX^S~l=HD{a_pn@~Zr5Jl|khTwiP)lTJw}y<`hvIPIKfz81^m z^Nq5>qo~Bp>xR~AiF05rUl|5x;gLzH&LY@X>a+Ip0(2S3nv*O()h9G<;5|6f491|V zLeT9z^}l~#X3dj$Wc?mfp6z&_=`3LS5jc#NRsq#E7okE5=CM97k; zv)Wu}I+Z|Ng`&7&8q0rIF5;*ZS!>*X1iOJC31VFLK-RM;2Uc8un&%W%BzJqjEfQ>_ zIAEi#*=u0RieaGgOZxV#?6)Ou)b830H$O#3N3J?bS}+P20Es8S&8JCJty1#~^g}cJ zBWV5z=zFiNVTw~^Z=bC(o22Tr-@dW8F*QIZMEew*v6|vuj%RFgl*= zr{|^>m2WtM-NkV!{Mg?nKmdux#hAkaDzMA0-mz`{jMjLd{0iu9ihMyK47DQvg|pW#<^|rBT86 zYXlc)$Ujp8Dj4t-7PEl))ykgv2S+b?@uwkzNyGf#>((_?}W zk9-h$p2j^07b6O2>Be9_CJKhAP!=j=8({(V04A`Ylyz@j?E!s-_7_vM@C!&(W=+lH zE>Q{?KH2jErLl|0-}VX3KV*|7d|CB;J~!ir${Ohby2;L#>}TzY4K|&bmlG)thN-+4(g=9~wS^kukW{v$AE+p?n(4o_ao{08HkM z5@^vKy^vJH1Uho0F9{KTbkV~?wM{wqGb=qcNgMCcWX)dsW#A5K>eRsckS3FEn)CZx zdNKLMSn&H_UzyM&5rdZs#4yv@A&^(M-#MOxXqApqV&Xk>-%9cPu2aYH9iTFPpW&Va znD!(Mt^9<1X;i|=4{1nX-I!G&SIPDsgpv2H>lBJmDtf%-dvSj)8|$S#&?R70hxRCd=UBJi&E^}SFO&9EI;UVOFX%k`VJ;^a z0UhH15??rKsc`vjsv>l0a=(kG-pjY67;ZCW4blOCar8nMZiqR$OJ$Wi?sf>BPt?Sf zOi-=?^s~W^z8F`2S0hY1zG+z6*Ywly)yV&j60x<%lvUbRS<8u&e%IXSYW|_mo+Te6 zcm@hYGK7H9qDbTe^=}Q*zbQa9Sff4Rx-Xa$hnQ~wN|ls}ws${b5%=jK7Dm_q!`bS6 ztUe||cxC*TP5I2L8XgJZcrMa`cm^ZrL^BJyOUGA!vlfX2W5$i`^td5u&Es2BwXd!8 zVm(P1=ririYGz*T?8OeC{`&y3niuW#P4id+EkIE}nGp55$^x|f;;UJjZ&xo$Dxv2g3ZFSAhANq z=nL`CICn-!tr?O$$1nhM2%#n~%zGQV3dN+7{RNnW1yA_WXmUo_zU~%W^ zeN-ha!)#XVd(6@(4s0E>7=*{M;4oZAnP}c_1~xrh_U|YGWWF%{ieHo|Q&qnx)!7Qy zUmsJ%p!89(+OESn#baS<;>=(F;n?=TA{<*J`jUj?2AN3BC9{Z(*EPpPZ91PX!4HUP zH>XQ|!2r@3p%I&K(=g_UEK{Q4F|eQQi$kXJ?zK>aTNvz zC;FI+*WSngKA$1mtS}RXy5mD#*KiX-Q$nhIS z1PJur|4;6%E$E|bB78b`sNCkjUz6`$-6199rGJ> zT08;RAV5EcK(>KdiCH*81mtTl0blH>sKYs$I|@fn>dFL2nxM&GA_^dm6mhOQwrZLT z;yvN*>xQ@I|3d+Y#f$cY(!7%YE^z9|4R6fv;dbim+= zbm8p@I3vV=wu)X`wYyXAY$D(PXTApZf%*Dwze9D*mC%6A?>E`^-NQk{1JWjnj{~R+ zk6R%c7`v!4K?ZBHF8<5t2ZVrO1S%c8G=%u1Nnh^%^4-)&snGM##nkY`a!nmtj>L&$ z)`HO(|L1SQa04aBbUh8;D^%WWvptQ+Fq5urHAf%ht4NY|OMC!LJc@Um(3{P{RmJ1q z`#`H=G#PpBvVZKPm@+@X^(rQ>Dy`TdPDX0M0B2{NRc5^~Y)k<%9i zK~?u5{jv1BhB4<2HQtKb73Mhx4iU!u{>800(9$`^W$%o^jn3q2NhwYqr=bES#OB$@ z-g`e}+jcSrb4k{WR~!V_RBt)Q%w!pWaFKYD5DCQToPdA)1jSoAS-ce@;)1RF^lJ}AsM)gRL z{wxL$OzS&S!%Slyf~I@pP$QfXP+Q_1A#$AM!kPPeh-2Aln552{Hnosr{-60t!1+|( zbBK9Qae10z_1MWlpXeI3RdMe@7Yb-!2=3Wig;0X0!Nn+rvoP2n=Oip8kR?hw{tA$* zz~1HpOW?&c3Uwq0{%X7i+QaJt+(VWfla_nZkvSAf!|t(w?2#&tL89F6DtNDZyh^lS zDSw!a52W*_NxMpM&)PcF>|Ovb*vxxQ6Np&IwUzudMviRhQ20C}ln%hyKmlo0@wsH^ zVWqzT>1eWn;lo!y*_s$eJ@03h!nL8C21W*4@0sV4-^oj@&Ou>+2m&``EEgFR9n+okOw4f!unL^HZ>+c00X=rs>&jL8}O+l+?u~&rW+d%r0jUz7$B=g<8a!o z?RUITu*<2eYbyeoCnhS0||D1@OWUj_T72dfB!Fl zEn?%7pSu90gEpJsrBryB)JuAepBMFvHWgrRtL1*o@(#X~eY;?a^bVz%Y%v@7vko$1 zdVCjLDdg4;aq!YFi4!bIskZ<(>L%;6kg zRLHGAEa&uWkU`T8M_^V@i8th|C0BrsknCIFykdhX3c>?611r2+x%XsE+qO>YegxLy z^`tJ48;NngAM9YlZOV!@`_atO>v`&A-YMYt|N9jayk}vhG`2&o;W-}-U3>Td$}Fj- zZPbizV=jV*U(kkL1#o)6PzI^M7}r~}P<*C}BGdwhx>=@3|4<6H<*&C&!_z+tRJJj( z9T{crVDvv|_g(i8cpc0Nezkiwn^>p}W(uohy?$+x#p3dMFp2t0wp5asi$HJr5!vqI zJO?273F3v>RS6p|JH@;yr-E>Me>HXcx^%jQ=-jme# z{}risb3bD_C4oSxiTtuf$-V^~XN2<=bGUll&;`j@I^7AIPUCPf-^1aVhseV2iz7Y) zK)#!ulIwTfoEc#PcT@BCKn+oB9e~PvQos@nD)`QeuZ-`UfW>y@^(dm$sJ#SwX^<}g z7BO`RW&F7*)(0N9EmJk-Z=BMC8##&vIv7P6VlDoUq*Dp()-{UgRN^%n5z>8WBS zOR;p<^-r*MPk5MvVNusy$55%4fQue7%tx67^zXJ9#NsLbY}2%}W3;i)5o3#~T@F~# z#LzMpkE913+D$4Rw&zBfUHW?IbW+CQY;Qm(T8ZZjgG8PT8~z#nl+~PF-TL#;B1%gd z(0dX4&AwSyd7HH0BP(t2;zmulDfD|GWkI>P4w6>N6P!_7I@d>95E^~guN_L7>QUA-L2S~C35>Ce9LiKzFZ5>J= z(3H@bzJ)^{WKEbUF0(2o*ue_CG4PiS=Rim(t(8*$^*v@Ul}Y2L&=cpQvRvzJko;`N zaI-yx6_lM?AcDd;qYsw#qd>EPmq*TbBlC6B%TXZ)8%13)wCSfPe>_#3pv~w=6Lt5{ zNu8pI%>u6|ltjRt!hOjBW3CU~t|dH$;l^>PE-XjG_pZ`Em)scpJjMk0d)9*oQB*gJ z7j`3DqT5DEJx9H+={=hP`UYa@?6*s{?(-e?_SS)FHIv2Yo8N@Xqb3KT#=tj_}5FZl0qeDLD8V@86(($C|HrYPk%y_`^)6d8yV#j=e2Cq z-GVg^`W-&=o}`rj^R?xaDbLH`GrI@BKAi?rm?5!0BMyN#+v{Y~P%!}0k>ts#B~z>l zv5P!9;HPb1;WqpMvFgcsF^Pxeu$91R@MA3)5`XrsA=nP0&%Xk#0MkpD|A3qHc$JSAQ=MOGW{ysbDGM3-@V33 z(6MW@i3A-ziu^c( zv&Bn&BWUbd-B`E>+gao z(klwCbNg`|6*Nl)um0I2;}p}NHXe2lJc}^w;j~H`K&!913 zy4V~*W3|!2B|NYql(R)Si-x6HcNxn&x+jS;vqJq5~9heafrrk8PJ~yH@lQKPBC<~!ZEIHd**$f-&Xbf4V*y_9W5ai z+n4_r7W*CqrN|hd)_9|=mL~Yk=^%lEF?l6eKpeNj1gJXOgwq9a1A%q~|J}jWBUltl zf8#U3&-3t+w%%gog1^_{tA!KE8NVoT6U0Kr(~$I~zqJiwBfWB%czlF7*DN0}or&y@ z;fAGR1*1Zy!2@x*ZMtyTfh$_-sV}4hdP@WXU<;<4elt~|L2`!K#C7wZI~18L%^@S% z9&a3^Olx+-Ghf&Iewi-YYGbtxllaN8ByOD8u*po+vanEkO|xC zS<0oj76HcZ=i$Moa^eB7*3M58dLmIFYM>#^*U5a5Y*isP8&n-}vLh5(K%VFew+PusCtw0ke_QOag8(k1o{pvh>4m8WwV%zYGcbX!vlndc<#t=H>4t5c zAcHMNVaqJ-C@$E1($aN%0iv;0-R2EdGFX_YbO2}pWXriv&0wOOdF)|5bzopxjY|r2 zz5>id%@$XJcAt~Mh%u*PElj}v7uVm&)YF_|g=KV?L={qkDs}9E-|AR(+IjV$;u9)v zAjBtqY+nqdFR|S!kez z#Z9^!gA<9*3z6ZVl~1P#ll>`kz7LA?7(IdwHnozi6&4%lVB96&o@s$7)#m%E_6X9|P#FaJ=LqWZR2LW48Hs1LR==bvzD1A*rXY}P`C;|N$@{_o#Vz5c@u$@FUyFffFROspmazG(#;}WO2>*|`~;C^LAq;KT0uf`=?+0UmF{;I|Ihnz@0~ew&Y9C^ z?yL$pC~C)M@(-q+Pz6&xU-JHUA}E)n*8_)mdbuhU)aPXZ!s+#;B2l11TgTxD{-iB1 zhWi*4r5J%^_JV@j0Tw@y0{9mk(;~Zl6ruNnr;5*Uyr4C<19bC44@Z;1$NMSki-tH& z8XBvcQzVCkx4@Me=3obuhaZ~kqllpR3E7TLSZ`+5+i!#Ddq>OfeIpU>Iw7p#Bfp^K=PN5uJ!MbJT(5{P3vA)HVk;u0~&R8ZNZ0A~9EZioURF5iD4gbWg6mvPx>TxUk$#_k1l$8cYZa)|kDq=S}nQed_A0(<5|27<3bV2_eOn z^6{hFB{K)T-QxU}SGRjuRB8&Xf*!Kt|E)6K7{0{|F{TygXNO)3g0)UujA8f9UP*f8$Rbifqln*^Oj?Fs+>WvgTq7A z(JJvH$dqp)LGnKU>n3>EyPyA&_#tH4>8o(cL8>G-6kzMSfefO77@ORTQ^B;BXDm}9 zApKWCkt+#)O1D7c(Lg0CH{jnt-?coY4!H(SgPvi04cUWTJhNT~Y0%T*6JU8G7emOwwS9<^+;w-` zK+01?Gmpj>5}uPOX;@2kIS@-if!Vgh&*_nA6GU|W&cJkfM^X|V7k@*2vZuC4U0q!??#Tm@*4lm%fvp;$tL#o}6fgut0J>a_;i%!F{5ZPF+kh z5Of4zESi*4SY|5ow+tkJmYUSIBjpIK`ioA-AQA|x&Tg+tuB37I{F%7b#cM=92VB02 zsjMh-wLF6I1q4Y?EKS|<*h~d<>&k~MP!fPO*wR%WO~_Wg4!yMOc+!l66H&N3O$y)` zt!`ed%AHf_k>h(r8E*6a3^7vwAYPwv^`)>IZ3bh1-H|ce`f4!Aa2N0gW7Z{ zT+$v)&6V^8g`PFLY*Bu=yg^s@GN_Vmi3~Q+EkD8yMbSzl^(fpS$j^4zpBpak;|Djs zgLRqFqko(2c^W%lrT-fYqg{-a&i&dN&%5N>;PZ@RaPNSf)gSMKjqu#uWkr8#h^o_F4^aa)58zj4 zQ8E|b<<9xqbG;d1d&sAZ{MmXJYdB`tm8E|gwNIzMi)P;R3K=*oX!5R|hH1$bsAU!F zsb!A!y%v!T5HU`s`2rnOElCg9nfR}qELdM^$A;wWIS{ZO@AV+wBL|x&hYWefr+*;w zePuO_C+}#4!E|;JX_14a4&@QX%+O8OI>{ohgw##(o~n34X(ZzvvFeYC1w0E@qFe!H z_Jz!s7HiB_eDA)N5F?`1wXoxOr7fL&2y6{nRJ^4?#jBI7w2U>M6Z2TYzqu%Aq-fG% zLhMkUw4$0IDJa$d2jxlkf|Im z(WFzM^`dO~owUMbN2!{p`Zg=|4OSLLQ<&A({jCZPGO!8QD9-*Jcs|2^jT^aQm2tdb z7kXd$MP#|=Sy9j_axjHa);!FQYkYULcz&nCRIV1wY?R86OY2y^_5}iVZ;qC;rq6lYxhN7tQiXcJWTGE@c#`=tl9L7p1f(3?4E2 zdHy+7&OL@n7_BbWh@k_19vQ8p>5rFgVLKO2FY9?!!=ZaBjtT{&aayX-lezm78U)^M#_@VO93(qR%Pmwx!w-FC5_zK;p zy+RYeibwajI5UsOuidXSKKAgue@zdYPV4Jv5y||+?2Ph$|MZAf_5ZM`UhrPDt)fft;e$|4Sy#2ezQA}N?G9hcyg4g;2d}N)!)0^94EA&ifnYZ z(*J7fG%}|=-5`ncsxCf1UTe97|3sud+D%8u^L}hm`WfXqI&ZRPuZGW?iF$k4RZL3c z)2*_^J#T&N=)n!;H2xtEy^h8JR)T{%l3)jty;n>Xs5TaM>V1omsM{$b z)n`Ewmb@;S=9BltNAjF2j~AQMFPRqH+dzL(5oLYw`OSK|&ne|B(>uDpkh2M58m^W8 z#D$xe2N)xrgo^@9i>t2XKgphH4s!H+^LMdyx2*rfm0fJMn{?ON!pGbcZ(s)Rh+6Y= zq^nKXwX`12)8TSccjccOuc~DH?j28=uNsZ&1*D+Yh4pF>i?tf9b#CS41jo`8Od4%? z1zGX4pAWszHomIt_j;!?k3Btq)>dRdt zDOG=BZgGR>5#`^XjDl3ueLM!04a%|0!Zh&BurzWKe>vH6I(uhpW%kG|$>w+zY&Yag zjpCAqoR33Piz(;&z27UMd%xMu8VnXHc)*6RfGT#nUlzg`eBp<66R2%OdlpU%0G|&5KBF zsin?`Ot+XRzIlqfN^rXeI0wNPXAcJ&z68)!#P!y}-355xIjz+`wc0ukPP$C?)P~Ax zzU#s6_!THkqhqQ=CFgCBWb8)^uQrA@O+kB;?(T%&ulzh&zP>9o?KY5knOgGx)KiX`Ml{Mmx@K}mCs%6N@9d{qjf>` zW=Su1lCVdTcGadfQP*qdQ3F+PU}V2nSGZBAALbq3N~r(C-@y>A8tNsnD?EzQ{ge6! z$}W4s$J+^)zlk2l`3|SU)1RXo=bO*$ho5)rxq(P&dFpFJ;w;{C5!vWQp%2?vR0hj+-v06+Wm50PY_@8#ZhWPx zm&VdJDe$n#i*aRxF{4!(VX5N?&!%VDhnT)jCjpJN=Cfa`VKNVYemr%%*{Gq*h|jnv zUN4%cYr@;1cM#76j<+V@n9h8Z`bI`q|r993eaaIwQ>@lg6=_V>XS2^8OU$WX>=wgRYJ_!uXSqXb zoG^Z`5Ui1%|Cw#>BHB-Sr~NtipfaVR#BExF>@$UV+QE>RA!5deNS8aAd5jn@Mu|jo z-kEzRMFI%M1MM$)+X^@7R6%sdMydeuw8XB-Pgi{&Z?X1w`_LrULq4e%ok{u&6?*p* zXJ7Y%su?Wpx6x#WzR-r~bf@!Cu+9NmT|c#Cc>#oB&BW3Q_9kC@l5CdhIz z%sPpICvkj~zKT2;E*H<+!q381bGU9#AKv2SzfA&lllMjh=&0p#kZ815`Ei55A~RlS za*&3IL!wK))z^PJ0wU4#v6hg0${`iwNdA2X<(NL2BdBs+bm;ez4Ce5|YdB3enzx zIZe@qvf441jwgtKu##_YKdAY>Uwn%+P>T>{G|J*{FgTpL z?myzhpSVcKu~bS|KCx*c-f!Q5Bvo3703NEsTYp)4hmgbjCEb$RX=~vNkN^^Q z3ejF(I4zn0u!3a=Kp5}2_U5LPG{q>H0Q~zqqhCDe#y=Ke$spsq1%u>sD#j|G`z&$7 zzt^=3gUG+Eu3Ve=Np*b>x{W`99U@~6T_8lU&Q7&fa=?Yq`Em}p{C?;~VcCn$w6=Fe zBVY%%#QkLwr;8o@N^P143U|Fa-SBDV#DJ~=sU6k(YG?GzJ6Hv+to8sAXx_d3cr<>R zIas5oymUO8y3+#;y>qX~no_HwC`C^-T!tz}ARa7hTl2@HdfCiI{b{+Nd+#$&xR5}; ze6N(YCgIT-$1r8r83Ky*)w4C^jgnC^jcTtdx)Ove)fWgbhNs^ybse!&i)Vqz`1B6C zzzz28=+NhPLCP3Y_r;net-|@UiGV6wJGvFfZ8HNet58wmw67EC^Sg^+$X(dv=H0?C zw@!5iUOQN2`!s)nG^m!<=D&!mS-1otT__dAh_3Bj2`!3;LsX7$jtupXx4JjiM2cJ2-t%sm@wzrX zMjzd04u3fU@_yN)#rE6^gZKkY5X$RaIt=3OnA_3hyGE{%h)ano~ODtzKoBahmBYR6DL9g zNj3RQ)QSl-oM7`b3;emtPi@IxYma&=4OhthKst%ZXzl%nO6U&8GON7CUlW6g7F(gx zkw&9)EFX`fQzMC+o0cZ^x}><^LPtTn)n~F4s%s9@dFNS@cmm`Hf80>(X--c zMz9Q*$|gS59ezx1-WJW^~~!KFy80I_0$C!q@SKw_@76)gEeCCfhDSYGN=c{TR*ocf}ayPsp*qDPyS zBL;t7R6|BW^7EfBwLd4-`$Bm(L60}GzRKrs>rX^R)UpC`23zW4GOzAo;|08po@QDBLX>QU* zY*Kn&mw7L~oyORhXdo22v1$H|NRFMU6qL)#s|@nVf{_2ciG_tsZSkLdC3EkUBM+2| zX$>aj0sbXQQ7BBs^WpS2G4H3=RGH3s+2z(wk=G!0_`DamTBX3f5R7?kJ7TxRoHW0Y zHda*k`RcbQ75^e}h%o(R?{cKLAEwf=o*v1_iSsGn2{yD&n^wO3Hv*6((t5Yz(r$Yl z9&I5M)+USi^-M&X zPX@EKe_T51C9TYo$oY^*6|*D4YjN?W6E7UOwEweDq1w1FXouZ6q5dh|hKZZbHCW)u z$Xa+9M^7oRq2=OtBN>0#t2)j#u-Tr}!;~mYr0i(CQv_0~D_0l$)V8aGu0U>wZr!=T z)c7>wykEBL(0{KT=u_gSedREP$*{vqHw#@I9>uR`7Z5v5iP#coFdFSnzqOo-vfj|l zVej5i%J{QX&Y-(_ato$JYq@ozer@T@9@_v)c%E|v`SK90du!|B{u@dP6CJB@#ECfX zvou>ge3~%25Pcm)DU+or41$7e*Ir^ImL1<`IY3}zz%6$!W^2LN*~Zd=qK2$rOb~?M z>&>90|FiM?z0fpJyc;!Hyf;%do(EhXZoELX#JeW+*MlUz5D0=J4>YsIW3yV)-Zz3$ zzdQ~;G6LN`nVYR=mA+$^V;lgYcSw#Mn9|4Y%S{^VNrHq>pxlp)FxrKF;E*z@6upN1 zQQ|CMS(@K0!=YkqFEcWs5)((&L=1f${Q zaNPRd&uY%@+cjaq9ch`cm;N@mnXH#p9~FP9Sk#E2o_5mxAGEdc!Jk^;sNKxVlY$jo z6nHq8mLQyXd?kFSOi<+Zzb6$6WF2;hGu!1x?BB-Hiv9$UB7s##GTtk!H}{314iVqp z+|l%Zet}?Kf0BxJ|2)qZLCIlC#V+PXIF1TGr`Y^VkUr)%VgZ4Zg6_%}958nV#pf6v zipkH?NfKSR|6#R9-%Je3uH34Ok!O#R7oLY*Q0`k(m#in!;@O5;eP! z3I8Sy{#VA*#s`8sJ+XiWo&WK*rwS!T&K3^J#o!suKVG+1p`z9M2HZ<~D4qBoFdEYT zqiR~sL7=PqD!)6Up^-!{rQ-HK1m-*twzzhQohryj!SZYBHD`vuz*I2-*uMw+6WHfu z0SGQ%%0qrU+-5FTp++6^4L&q!B>6?wKk`?{?dF~f!j^w^&>|m*B23A`8?hAI7;z2U z_k){(S#N1}&z)HeUs!O8B>-GCpI!{l>R%5|Wv<5PZlwPc>a%Xj$=sw0T`B-CT}Vny z$Is3b&q|+&$?@Nu2CbU27P)T9R~U(S^Le{$AAaK$@h^E73;K-R!Xy;VP;eyu*sGZw zQeoO5izx&R1DKMOHeOit{Oh35kD&hDiY{^*oMzHzG}OO0^s3G(=z_abK%j6D6d03< zxHoFoB}1_^ZRR4^yuGFOHqhk$k!vkRO2II zuMYtK%R`VAMT5 zgz~Gm!e`((JnuSZ)?wE8v&RBeUIN1ZX`MG*Mz5@qID|^!*U-d=ivHTZ>lB4q0fk9S zZL6&f%zAB>txp$ZdrHrgk3`iSA^& z;j`j>V3uXRwiH(~{Idi`zwL94W#d3P!lc4jJq+zOXl(}Woqe0?Z)_}0p<9Q5bn?7n zOi+LRRGpF^X2pAF_o*-O2M`jCenQLFfp#1TPI02#*dtS9O0|SL1!)(9eCdRcZqgwW z)eLypFlq?0U_qi+7R%F#o2V2^rHh9n2meBfhA$VAyAtuidEY1t_Q*>^O+2}$B_N~D z^j?+dblRuH3p(DWM%fPzb7J4yV^HZlnTj9IBmHd^TaUc^5#8 z*jF51CLySEzw9+3tfQY6?+O$f``OKGW~K^HgOkJXSi3h9$w%17_OcTWT*3N1+fP;- zm=F98{XMjRNey%%Q>rP<cRyqzuUdvoU_+^`0EqcIcV+@GX2Y5 z-}}e*=e6k*qXRvDwRiozVXCInIAde_3||wJZ%~BMbw?*_=%Kw0(SZat5PL=p?ze>j zHJ*bb%?IZfV3C|s8pctPu8*a8+QGi}y$))K^NyYz0=>$MK@wfL?hc`5OL}^m8@}%Z zD?XhWON(ypyISnM*sq(wNt!7OzGe(M<%$_&Lc;4v*VG*f_9lC>n#lvX3sPW8rI&;y zz1%I$a;6)JjCRG`w6S;)#3j!jIZOEFdciHP+kv&%2R`ev6qyWt)>a(rXgwluYMjfD z9oIICZJxVMso1+{i_v}Tm+ExnP%V7tK+s*XThN0b{SENxDy&FPqiq9ajAl5>Pj`YR zci6LjT=CvGZN55a_gx5tB0H!~ve_{vydC`9WrQR2OZ$8DHmF16?7E;#&{E}xFx1Ey z$jOGTQ|N-&NhoH2dr)QbehCCDg}dC%!hi-Z#%gW#CZ1wx(5GwOlV=ddSun+sguVQf zU)Ryal$raz?gcupcz~1u;}Z3E%tou=Y;Ctbovjz!XmIL*^A?2Z-;Fji(kH+*lW6-p zQTyA*F~=J;-QbVsf|jbfc6z6?`%i?86Q!kM_RDceK=&t{!ZQxbi4>$0?enz1s`n~J z4L#ADFlF3ablvl>zu^Bff?h=ar(HZIHRUSV9j@ZKBvIR|L-vDur?tR(Lvt+1bQ0`~ zNc!3dptqTzEgEh(@STVpd>;l=a#_eS_7f`PV^NO{vl!)R2mE)?I|7NxEyPxU>)rmM z)SAuR3f+MG)pd|iAgpWtm{~K9&-?1ej5`%l6%K3U2(WG%41f(~bOHNi(h;nXP5UKqIC^uT8BW5L8OSHkz|hrk>^2;$1C zbrPFWXYRP12~)VH_X?EYGFxR=wdhsum;N1GEA;?M&*;h?*=|2wr1t3+OnOOl=ZotQ zXz|$?E#3cZX+~)nIMWz#a z8U$;Ict$$~xKOS9(JeU?!AbTee|v0=-~~3eAm+5>y%oZxvsIzuO7p&+?boMo1?QR$ zp!op>))J0uwnC{9ZK&kT9|FyTc=63q4PtMan4n zku==CKcwNAfA)zT?4=LRFwE;1NoXz!(q`tT4jC==_84A~SFYkpE2;E1!D*ZnQTn~s zzs5lw4$~=;|Bda69m%}A6S?A}Z6I2;kCUf1BlhYVPxOmxw&lXTl=8(^yb8Ti=;_<+ z3O`Gx9g==VD$ohYfnf&hk+(9H?Q)KqRxHO11H{0=7XPdlrTw+SJHa$!*3@2#|pUO;hw=OJ4ASG!mzX?=f<;(JBo0HLTWiiAX@61~L~~s|J!kC=4?j)$TTkn8s>B zof=%&M4*`x$>q3bz;kS%ELbJ(WoetriJn)UaW4gL5d^*QA4pJKcT057*XzOIv-1h8 zVYRlnctsCwapkxnEihVg?7r3Br}D+=O3GEc*XT75&=Q9eVQfI%uMwty^4t{{?d+n0vS=D$Kox-2k50h~A%XcF{x2BJST zH!!PeMEsElQg4-66LBS6poe9}zn&Vm&s?tT)iQzXF2!HJHGXSSaQxsfY|^f0AATjg z$l7cP7ui8X)Jg_}m=H2DUh-CLpjjbQWVjO$DWq?{bX;ZoX=e5Z}>7k*Hcq zcB$h$HJ2|tIKsm^vRCSPI!}8(wOx3?XBlLlf98p9AIN(Wbz^6(lCq?~_Cl(~@q7E+ zB0@oKpOw5YxJaQ;i4xP8EN%|7nC$VvWl(`-gz2^>M+JDlJOM9G7dPrIU%RfLYZ8Jp zE$X2Dg5#D79rCWTj9YJL^3b#8r(uoYT*sJG7cMN;sFoY3E!%wY0zNqCnIP6D%aiST zHMH?5Z+5krtpN_cFfmZNHz_FgJZy8MhK`Tl6a!y-p2h*fql`H`4=2DeV(`=5+#vR& z%fKaA-z=t{ZJsT_CMTuR9r>_jUc~wBEJ*X?@eDIl&>z5^F`*=ULqZQj4+T6$>Z1J2 zmK-Bv`4|AAF*5L12NrPTVB*0hNu6-nwO|-ON;Vu-2May%0tG8B;KXoM1Sf7?)e!B zin%<3P2`h@(1mZ(Ftg=9b+|b#9S$6Gtfyf=jv$y432*m}c~KbfB}wR^Y2ACkK;Ju% z1BP4@V+Pdz12_yt2)1%&hM*TXql9)dpYB!4np54B%__Pg2H=DTE~3Rf(sAejNm*=|KHbqXI6nB?iw!xp`_%0+F1=E% zDU8I)8HEg785MkZm~ow2;SZ|>GaES$-WEPsJcFfx3}jt}M7VusM6iRNo4uv{(jJI3 zCl54m0K?gk=|7iq8nNKa8*mjk@rN=#`7Ia#c}S`RD*h2V zYJNDef&S9r$RMT4O-e5BPSqLTz$-`6|=oJ2VA!}m68pW6ovAY zO;Cx!5&K&b{>ms>s)XI$4`gqMlSeorB59By6(kup$`R$q5ztJk1ayu%4TE*?CCB|H zR{}06i}y}MN(Kg-9Sq3P=#--c{-CdO;)Bf+|3zjGHB%{F>pmZdQ`@0X0G;AY&|tU@ z!x>LGaeU1YC*3};{EzB|>{@2F0H&K$3w$2Sk9(U|_K_IN_4nJ za0`PlBg3pY5*beN5bB9PTnk5Jg=^GMr}Cj-gw2*S>ex>$Pw$y|%|L?ik#ia>1c1*8&}P?XB%` z2MbaBXH2rpO(Pp~8W94zxVc3WHx;9}z$Q@=r$MuXm>J{@aaoujk@@i!INTp(ZQA#v zzvuZq@9(1rtE(!D3O5uY2vQW-!H3{@zx5R4!}r5;|B7&Uz!aipSZg%XqAnw>q&3KB zAR#u%Az75#_Fa-I5M;HeM51OixRZ%#3Ab8UaXc362T-VH!C~ZbvfK#6^XUC#ApfI{y18ZVIV<5Hbpd(h^q#Z@nQ?S44hlr zIEF5mm@QsxQB*WojdGeUqokd%#RxZnx`7=yT@*!aLmdPlaKeEDhYe7S)4>n~x^!XC zn=UmnA>O~_3$DCavuP$798agy_O#Qk=}kDGY1-m&IBd|uX0)lMn6atGrW^w=8!=r; znu?~P7NgjprA#jdl`bA3kqicxiB)4MP%vb8Moi+sPT+}zb*=?#!wkv)%UIFch_oeT zJR}=hN{_*OG;Yd)VeIbg$TEa#m|eO8lOo1>EtX2isu|$D82nIPNb5In^5v^@1s3AY(OsT7p$cX58w#Sws~JUm4D zC=v*MmiMs0A#lKj;ZO-~)x~XflG}pCXHA!@9xj&qMpj|7=&&oIQppwsSydO{*+}Mx z{+D<0dHae-=M((4C(L?A$Ud|`TRaf2ySTNNF730|fB8&#X&=Y**IXEwxia7t2D>)f z&JNBLpXwUB+13{R`maL`J%_3J=})fD&&?m|zV_i;C*N4tN!-(2fsbsS6>4tY&^plq z=Ioh?cZc^!h5p`G`Oh|vyLLAf+A#WPYv0cX#z*Xj@0+;0sAu;1^|50eV<%n< zM<;$xMZdYXY0K3=zwdnerHk>AqifH9yBGU-&4aC#U!@B#Tv<1^A${7#uym>Uc-Vk@Bg617+v)ujLKT zd_K)i_h6NEv$aU&8t35fqd~Qd-5Pr8$Rk6OCng8ibCIbx_dFe^PfFu8C8fXCFpup$ zcXdp!JD2Uxd$RubKMF?M*`HeLZ~b;-Xsp5I8l7Ne6A*&}LP>`p+$tptdqM(4LLf>oBC?29hGc+%$;4!UAX+0TVp-g7 z0j)$(1ktKkqaYNaZY(OYSy53$iv&di8eEV{gM#gk>z(JBdB5eH^SrkNQWTE09<;1(Lu3gO9|(AX^BJxx zi2dMrLEr`nykbLeC~rd|kHW|Mc!M+@U)GKwVO;Orus=>2t_2J2(oVa7P;{Vib&%TG3e(9 zej6?j@sSki!jEtchsqX7QAost*-ScKD?ktk_*8diH+NTmmOqK*Pa%{2JsGZK62)yX ziA7;BTp1qZX)Y7tB?(~>I?d((!)1MuJLv?WSeuy%O9aUh79VSbTI)D}aW?CZb!JiVkf&*bp4YqgWlzK2CxvrDwDX0MIM0KiN>o5={3-5Wf( z6tP}8x8YXd{9D-#!K-2njf;<#%URse1y>F)pE+wmHA8OdbrSns$1`aI7?nV^;=d+PD^BC!yXuPBIJX18 z=QRuSxVY3G|KfIF)A_@|LSMt(IwhaOa`{|vW*{bHD*St&Yjq{i3m8dGV95-5BlJed zD)LI{huS#k&`c5r7e&idGd7PA`hWq#&7vV(edo2CS3?M z=hP=b7R-N>*~$ZDA<_h`ooOZ2wwAkYRa<+0aCk&ovrkMbc%CzS(X37H+*Wz+fyOM-_?kZpzPs5*9`9yW6(ZsB zHZ3nB+=(-;_8s9E>{OL(_fb9~FAd8x56XI|4jWi>{MPms>Q9zsutC7K>#A3949gf( zG-DYR@>2TjE0*5Gu6aTz{OaqiXU^2KyN}uKMJ!5kf8WP^zrJkGox zY(;Lv`?eGBetn!}adrwU;dVcsh_d?(}n zY%HgsbTp+eW54jNDfjNR#X+tcE&I^Iu&AWt)dV`uqBZU(ydu8U?_K1tZaL!x9qV-+ zdxt7Efw=>KUFWRyolnibk#;AX_0RvqQSwLD3kKYC6swFFXtt^Jj76crO~JXi8#lSv zcRftUMioY`ewEM4`2nf?Qzz(n@7y$oaZefL`r%Yzrp?tf=~?U&8&SVxa|0)QPTk{| zJ$Ftx)AE7x-n1FvPH`#?ua=cxtVbfKhO47>?w&f7hAxUeb=H;Merbz*oTSby-`|)$ znqJ-1*y%QAGL!(hnV-Ed!NA^;nw}3okTiw?XY&l}9w=GW7tUE54EK#hzm3e^u@&mB zyP*-^vvJUEly@vS8Dze6J^+e=gpqV_2hPJkZ zc=MW>YZqreeRR`Z zOz=-<9xTyB*!2vV*6tq8xqK`>QNKK^Z?nB}lYV(>R6RRv1~t#hdYkbRda&ZauzALk zBz^Y%S?AOA7TM#J^Y?x`5daA6eC*ew^AqzOY`5EcmrEaXRj%H*{KVLiUJ{Pat@d7h zbcdBS*XCZ}oFZqXt5FeBe5gdfbw?{P1EbX4WHXjv_~*Q> zcoWapvo-tKm+sDzZ~G-fpuEEA1R{(`XmgPErmN2mV{F$%hr literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/dit_m.png b/research/payg-sso-full/img/dit_m.png new file mode 100644 index 0000000000000000000000000000000000000000..8efd31689fc717fd7fe02e5c72c7afbbbec269d1 GIT binary patch literal 1535 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m=!ZaB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxOgGuk#7M#1QqR!L zz|zP>N5ROz&|KfZT;I@G*TB%qz|6|nQUMB-fVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7KMf<|~|UP^v> zu_jo#udkJ7UU5lcUUI6Zi>(sS0KLr26e~+(V<$^)um;B_?+|;}hnBEkGUNf9}K`9}(0BEyIYEfocYKmJ?ey#%8$5xrR-C~T> zJgD9j+-@UI2$*<4On9mVa^UGcH4m8Bi-4*6U3^kB0|OH<1RO&u zZoLWLop;4SWbe10z1t=WOnkaBKwyQyg%6Al?E*CnP4oH}Eq=hyQ6f^(!6wke#L3E~ zqO@tXYTWy(-1AR+3WaWOoc{IHY^JAP?sC;~&+XEWu^C^U_a$xIR+N6*pkg>RkKgW#I2cC#|dX(^gK-+<2(;h`ZYHBgc>Y zx7@hVL22(c13n2Z>+42eCcMbm)XkwIIYDXuAJ4ojL!=L4mwv)4@TikSK+Ynke$6>oYT{b2fNUGMNb zH+{cc=ro(vL6;&{mMqHV`X%e$v6gA4VKURKFWU1i_?axc9eTw6!bSf{CYvocS9N?p zE!)1XLi=U=dPj%($DBX4WQcSb1n;@@DENejtlBx>2^&6q)>t6ga>st3UZ{W@+Cz)BUe<#WZ^+9tNj17ObWsKs$)2u$F6*2U Fng9$dNJszx literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/dit_m1.png b/research/payg-sso-full/img/dit_m1.png new file mode 100644 index 0000000000000000000000000000000000000000..1038c94a7410dab729fc962c32ea56815cb57835 GIT binary patch literal 1530 zcmaJ>drT8|96!onhKO;9B4)^OXrcq|MQM9SJB7B44hpQ6K_p=w*Q4Cvdi8qPmTifc zA~P!DoVo`X$EMkoLFWswak5PV1C0#Ez%BE^oDVb-)F~5*yCUHJ7`x=|_sHk-`My56 zEjd}Qg@!B%0RSM>kghXH>r($aCs_I>qfHIc5-IBQ#Wj4f=%fS&NU`um3~1meD`R3P zi+lZ#j2Zv}V_0*(m~YG^X`X{AKL&Pjc8LuD>Qyc~MVB%nSj1Ran+6*3orXZxqJi>~ zjHuDBWlGre3V~Tuk!7YUN@>CZt$GzyyGTiZV?+vcab-3K>C!-xx}>!CUn3AW2@y** z(6glSjX9u}7Z@-JRwU4v90!#Ij44n8m&b!RiYXCPiC~EdC`O_RGLZnM9!QENSc*xL zE^R87bkaa2qG%@(#OZXx&P13OtO!OB1cKrSjweWn1c%!uQmzD>BX(Lr$2e$#wTmoo z1O19r5nnE9ASu&lC2;l`S({_3O;W=U7iC8<81 z4w16aj6tV?BmtOZEu?}_V5&46N7M8v7^YXHDhZ`N6~_`$d8%BMlse7T@pL)I*u-hB zomFp&YneS4Y*sEJC4>0q`mZ@pUrFZi zZ)aR99cFyb*d((HlB>_-VMzcW;|;nLv+LJ8c|P0EtHV#-_YQ0bgN~>dhR7B|@^^ur zm=~fq?!WQ*%@t#TvZ$b_h5%1`rAMY;1|2!PyzreY)9aofaa40(fgvnG+(e9kgeO(l#gx*h{?$)`!k!L zcPZ&w{pF~_$U0|x`GV1%$LS$@=xNV(!aGwTjV_tLm&?7zs)-8tm>b4 zEgr9VwCb1bqne&W`^MaN`V8^t_`y$VRUU6fgSPbhgHiQ4dkw>fJ%t?sL|fJ7FLt;C zYcDs)&g;3Ia$f;wS7zU;y?dptxa~p0mXg5WWgm?2Pre$J&Ar#!*fJ(>dB0`uv7o~h z_<_A|tX6*5pd_ISCrWbDm)x*wx;0;hSWm~7Hm~H|nTxM>dpBQHoC5w1@@eC|=c>cX zdbhS8yGY8~s>4qX!>iZVpPk@qb{&0X_ql@Cqu1_f{HAXH-o>z~>TH_1F?V^BI&SBi zOh?!Kj5GX1Kz&R7M1|RXFFwN%d*DbF9PuD_%S#18f`XC>kN0h3l}r1+CWpAW5BlWY zW%UIb-BY3Cv$#v9hgTi*dpdrqRmZHYg1QzqA0G?Hdp(ATMd|sik-^72=wQ#2_ipxu zTsOSk@&nQE^0+|c-W?=AZNFLfN3ZW{;q}K&F;(Na-Q%sj)z-f%`?^$}XYP3>Zf{bB zvcD7NWI2Vb@QSZ&g7xaO?mX?f)Aa^jW&5)ODNw0ix(cf&c&j literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/download.png b/research/payg-sso-full/img/download.png new file mode 100644 index 0000000000000000000000000000000000000000..cafb566fe8a31b1112be1ca12c5db7d73522f618 GIT binary patch literal 1023 zcmaJ=O=#0l91j#^4*VJ(rWc>t7z*ZdZMueLTidj@V9MwU4lgcEUe~ZCFH7FmY={nr zFi#?$oFI5|f{1qyPMCFcAkHg!$67)q^!8dGG!C{eJ(?cYUmQ_CWXX zZi=D~6!K~*T*I$xANhML(}Af<73@1U_n)AqQP30DMu4LA5W{fY(^LogshYrii?R% zT#Sq9bSj=1Y;jd&%-PVvEw0(-X8DfXa2RZtcvhij%|kQiAsaN3maWdQs2%m1T(e^= zYPKVnBf)TCYyWC>%S7fU+_ndo9NMD~9Ww788SLc?ch||Km@TNOaBfyo=yTgvd4lM!ZZfJtAbyO-WAFCXpQ*v`N1-^dp?BV9aod+Xx-^P4Yn O;gu|8i|V8F7_bA}6C6o0b~Xs3x^ivs%=lPIal5y49lr4QfcEG^`O#Xi`&}rD@G*L5o__ zDlKb8fkH(}DOR=wTX7atsDig5)liMqRIRGHTB@TutE+ldclFdj4c1VNs^J=`iJGjb znpM*^Qwz0NOSP(&Yo&q;E2>n*m973Zn}&=syv=Zf8{OnqZgz`1-03d&a<_Xt;6V?0 zl!ray2~T>;vpnq?FL=>QUgc%4IB@95DaTF@LD+6=Nj9%N+)-#qW17+`&1p$TI@6V2 z=}u1uGMJ%^%5X+9k;zPDR;DwPg)C+%tFoMR0NX*^Zg0u=-e=%vsXr@6zu<$TtH;mZ z{Qk}P&#wRQ#aBPyIJtE0_G8|9^Xkb1oc?ouTpK4>{=I+t?ytMY&#r!=PmjL7_tVoG p?cwRKZ~wUY;^TXl?tK3G&*SGWAN_sd@qf>LdvWgNM;DIp{r?teoxuPA literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/edit.gif.bk b/research/payg-sso-full/img/edit.gif.bk new file mode 100644 index 0000000000000000000000000000000000000000..d87da1a275854fb4d50645d07b8ad5c1caa97f32 GIT binary patch literal 81 zcmZ?wbhEHb+3lK(pSrl-61(@MR1MyY3rLm|pY`~<15+n;}? zF;Yn>0pwlT+IkT46spxNbE10vFx%1g+9@m9a7H^j$7DW-P1{K6ndfV@QRem>Vv?o- ze%7(RIsNP^bGe3)?ezwI=t&Od;Fvc2K*Vhbjtgyh@VW931DBC~(av|rqV4Tdh-aah zpT(DPu7!N*&pSuYdHIrux{JT9AD8|-bL2|QlLwB>Gw0w)T=;Ws3_SK@&R8XDjK)*< zlzOhC)ZKrTYB!bYG?XG&Jjhf$8YA=%|3#BpgGTFxTSv5ObqISWl&oPE*m?on{EFipedmzp-7jAzYl`FVWM zjdtrNz=zKVk?V^-HC$ZZy5PGsePYn_!AR>vJ~doipSs|>^n7B`U-bu|X` zI;sC#t?G`h>bAbkqtn#?bd=uX(N?-mqcclGC8JG9qcfvM$i-un2f28CW1Plhq*SG$ z)N+ePM;)qYHA&TUo!3KYiB!$f@L8uIdi=sV5C5MptleKvL3~&de-}24c56q6wQufg z_Vw4kvGpx|!`i>>5%YOkue|Wmi(kM7Dy?~CZD?NT3%Izxeq1((b$Y}ZW&EJ$vM;`F zZT;YS23M{n+xUa@p{K0#I(zQruk&(;v48GK_W#kw_YV!S&t5IM{>(LU^u^a~k7t>H z2eeR1cU`X6C%8Tep%=!hzyI_o{AnopQYVcc+K>AD>=|p*{|Ec>-k;?6fY1uvqe~Ap z->=sncJW-XD|c?3h7O~P8!{$qUU;SQRX^HNYY@lq@vXHpA#0lV1pZ83Nn5LQAuT^~QL;LEj8;|GC?Glk&1bu7S z_-0)j$K_kv{NV{xBd_h!^@*AF`pGr5T((ag7nh&WWF5JF?#i3#?m>~cK6970Z_KP~ z?kBP7nK{0;O|!7CdmooQxU?j%=-j1WC}tc3J^SoiOYisZ#XQbJJ!T}CHOjOzS}7E! za~^-bEwgWE7iusg>4RVDk3qj|%xI-hxa^*#exU{(N&H+V^~;_+TJa7oZQkEMQFh;~ zKfm+okvvV(^%(Edd{2BQZRX7{UOG33o@EWQhcr8?)%NWh;JpT2?uc!DPSz-EzO?!6 z$+Uh=Kb|kj>ZORT*`v!gpRJ_M5H&+-7w5hjzi+QDK7Us2w;x-6{QCo1Z$WLz$-91s+`P#5Ia$Ydp7r|`sh78>et70@ zN@RV^ee~t?vrpbIaru5^`>bQ@vBSHC=-ao}c!JF?HbxWs+O-5%ZYEg$yNfNtyGpG9 z+sm5wDplK+7&QyirX+oDQtKw;xL$1#>T$h7jc7flqZn7ZxY5O%@pplg1mvG(5x;dg zK`Ij4X-Gxmcr(FjgEv4a{Rx?j5h4AiYah~Xs@P_vFz>92i}DUDepM3a;WF(TCf5j& h8(nM?j*?CLvts0Ywpn+Mv8BfL7`0kXkWL@j{{ymJyQTmD literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/favicon1.ico b/research/payg-sso-full/img/favicon1.ico new file mode 100644 index 0000000000000000000000000000000000000000..5c1bf556a8d2221dfa67eb4eb184b3ca64e88136 GIT binary patch literal 15086 zcmd5@O=w(I6u#-SjrK3GSpOC#AcD9G2nwQ1Dr()iD!7p*YC|mqT8vS<$-^$PoVA-~ zsg59s5*ig|+Qb-S5X2M&7mm1bIoVBN?Dd@Y=9`|m+;`v4+&41=x8FVIeCIpoz2?oE zcjt~$6RM=9rxoF>x^!5n=ao{kvyuG;`EQVKZmw%Tt<>vhlzN6Z6rzmCPZ0ZBe)&a> z5le~*An)q#?t_@eP_1s66Vz&l*$(zLPg%)^GiWr9$$So*wvo~^&sVD@=Jp(75~l%v z(y_ih_v{99xrUJK^#*$SKLca8;oulWpe91%ImEX3GOMjX*Kpb#A3W4G z(T8@DhFO!}=cF$wf6zE;nL6;lv-noojQO-t$JB(M(Tw@DQOBl9%|U?vk!5; z55{q_`dRbc_ZQEm$wPg{H2fsa>K{8Np_#-*9DE-=#w-J-N`vg-@bO!;EFg zlU&!_tdV3xi|^$wE_g}k(y+xYUVQH?G;MMA1^fF)!AZh64VPbP+ITXaG`Hoa@j*A( zubluNzAT8`teB;Si<`AB_%6*XG3aH%KVoUi%MuIzsyzTr6QvHvd>%8j z&6?5%r%06b%z2S@S=+2<+M}#L%-URwKVS0uSkZM^f7s_)9+O!cw&WBwN3A&I&w`_> zEqf}W2dSTSK1d(`A8Bo6bA1#-FO1iI|M5}y<52RYP8{F2ANBd!Gt}n)59&Sb{Yicg2rb_|y7W-< zgIeuj7ta;Ddgtb8=rFptK4Y@xh1beo4x%l!hH(s^+}=Fnv!;1Z;LqfF&Ii_zUAcT+ zn!WotXQrmBhq&0vPg{>bN9iECCc9*QKSa!iahj?9T7}m>w6ER1`FQHwE)ltTFl#Lv z->hrnxO}TS-#=k$q_thTSz>0rL2^wkmz|}Ki@QwEXtIu6KX>KLclV&k+$?jKcGj3# z*W6EH(=&6j+BVJHzV3Zo_TbWzyu5Rley*5t4D{^Nx0XKW--~&ixq3`UGHVoRC$y3) zOy@lOd|PDS(9YFhLehu7)EiNt`TH`T~#b<3FT4sMqwvU>=G}7+%#xeP->q`fH zr9odced*Y~cL=pBOCHU;0Jr@O?e5|8ab8m**nx z`xJRR_mp>Hj1RL9U;*H78BjW(*@xh`Lmww|*3 zR)5XEt~coMXYJL+=g+Ex_G8Nre}6#hEvPLyY1i+Nn-=*#C+lRLC;fg!>ZR>z5T5y) z5?LSfEc){KIZNI+aru5^`>bQ@vBSHC=-ao}RD{hg)=QCn{d$D!w<4_k-NhE+U8UB6 z?KRDNl`8FWh?<3IQXqP)Y3U*!mTxJLVi$u&Xb gdKa67C9-LMR*0O>HtQ}jw$$VSqgHDX(&;1ne}#6%IRF3v literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/json.svg b/research/payg-sso-full/img/json.svg new file mode 100644 index 0000000..a4ade48 --- /dev/null +++ b/research/payg-sso-full/img/json.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/research/payg-sso-full/img/logo.png b/research/payg-sso-full/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..687e1a9bc26e61c210cde6950f8c33096b844129 GIT binary patch literal 14089 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 JY85_2{0}S}#BKlp literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/logo0.png b/research/payg-sso-full/img/logo0.png new file mode 100644 index 0000000000000000000000000000000000000000..ecc0019f9a260f7f7501d6016e67bd5d886aa15c GIT binary patch literal 7277 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 Z;1Aqy6fYML$$9_)002ovPDHLkV1iS(w2c4& literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/mimetype/excel.png b/research/payg-sso-full/img/mimetype/excel.png new file mode 100644 index 0000000000000000000000000000000000000000..3cf3f34b5f8be6b8ff62908267ccd77fc42d1fd6 GIT binary patch literal 725 zcmV;`0xJE9P)mLV}j1ElL-yv?w=1snA5Zh)@zT>Bk5+x(Xsk z$C+__@4nNS`{qZ>=sdo6&pns(bH8)0sP5b`l3b6UlCA^Fe1L$)FmwakOk>2SCr*Es zlh6_8GZ!009BjAf{f!j2aV>J~;d090A`89FDU8Vfxs`IM9RlrK;&^a5U zKv!zMjaA{&327w)jcA@IhIeq2slc@7Q;IkxzM!dQTm+SX~IZ#3NG7h9+ zg{KucYm6krW;}Ymz)d8IGag31QjFIn=@IO^{(_89SLwWt70lQl5Ka8dmzExswBjaV zWo#xJeY`qa{tAYHWz5PMzSnYQ(tyENU(~c1%%sU)LlfVW-QwvPd@~2>x@ZoTdjUT2 zjHiQ0b{3hTY7Uj>G7L@3;X;i+r(dk~Z>rMp9tbICQx|_tTT_jHOI=-wSr%oTk?a`2 zww;x@L&fPqammY|ezYMaW!?fi7a1b{{uW>WPI4oTieDgJ00000NkvXX Hu0mjf7#vS4 literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/mimetype/ficon_pptx.gif b/research/payg-sso-full/img/mimetype/ficon_pptx.gif new file mode 100644 index 0000000000000000000000000000000000000000..4d19e2a7dde70a7cdb87443ad9f3fb0c27c5d643 GIT binary patch literal 996 zcmeH`-%C?*0L8Dm+!B&ikP%k1q9-u}32jWKIJeo#xQ3|datf{4&!JFQ)cg_pAUY+a zsE4IKNUy!btk9ZJ{#d(nyVuR@L@nIC-s?7J`*DAL)BcHG`aGP61BU|#j#^t@SY*hA zGNCvG1qa#yFYrLvh4Q$l#UCU(3jojUdCVr}a>H_700g@0&kKN|1HJ`Q1#+zzsa7yC z+TKvX1CH`Lx4g~>jv*#3wTLhR&+&lryC`%PYu0_L*M4r$3cKOeWexz+@!?y20T-ct zw_*1AE#iwk)^iVm6*C5fTdz*WLLaZIqXfwUCcJ`$aBnDpCW&8k0HaqtXr+qAy@@{a z20G`dR>rm{Vj1z&mI(kvR+oLo%S*;9qz@sc?L1(j0}q1^dweaB814xN{75sL=xPCp zSP-3aHt2)|gSS+&Rx^dUNz5e(TxiWl`P>V4_0g?O=4E?qJ2YKazD;iMJnyQKN7w!2 z*NN@^Hp~d`SX+aR39r5!0I=Ao3lH39I!%r`9leCbHi>A!M_{uaqlOdM_>dXZtGM4G zz;SGsiG9)Ttd__7Tf?ikuoLBZc70^XKimoZ=N~PQlN9}J&fU|!Pe76>C}n@P=Bmu1 zv|M~3wb(=%>1j8+4Pof5^n!L~%m$0fj>*rZ%5?dv$&Q214vi3Qsw`E-uY`{O(OrWNcn^^aegzq8U|X zDW24f*H{he{$j~%+aTPdK5<;#a>v}1mSa7C_J~IMzDbfPsSU`^G*0(+9@v*xkF1rH dbSR;pg~5&~WtupBq#&V`S&4=5DzONX{{d3JbglpZ literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/mimetype/html.png b/research/payg-sso-full/img/mimetype/html.png new file mode 100644 index 0000000000000000000000000000000000000000..00f48186d4cdab6946b4868f51c4c533bdd80bde GIT binary patch literal 743 zcmV?P)9gP_PND}qIe=z@)f5D=GQ5ru3evRGJ( zVk0gA{&0h93AdLLR-Z|JMoLd#Vo?nL9TL z?cZSZZGYwn) z16+ISS>#NgGqBd;oXdy2@SYR zpC=4MN~IFcIh=E}S}md|qTlbcySvNL(Gi2e;E#5@eJ&U>I5{~%DaFdl3Q3Z%wY5dJ z+huiimCemf;y9++Y_h$*&FSgs{Wlt8{9rI3%QB9SkEz$|1VO;T!2#WFm-Y2^lv3>N z?GeW@#u$<$$=xVZQ&W}c>FJMwiz4CywAN^?bI}m+@O5Y2x!!0rUK3yhh=->7ACUrg Z{stBaN?ab>g=7E#002ovPDHLkV1katZ215H literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/mimetype/image.png b/research/payg-sso-full/img/mimetype/image.png new file mode 100644 index 0000000000000000000000000000000000000000..7b594f2c86021e964c01be88df95334e1c487606 GIT binary patch literal 972 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl4m>B|mLR|m<|Nn>SPtU45B~4qN zeEO49v?OHJmoHX4dk(d%x%S540lKXR7~6-1G#DgGzL$K~l4el&tHHp?JQ=89@?VRuXP6f=NR$UX2zsE(08BhE z@GXFW9jN2W35jn3ClY}^`vR0{`Tzgd3Z@k-87vvUfc^)HXaKRqHwFd=AT0uA11TiH z!@vaLF*1JZ0kS~4UNJCi;$UEu|MLOJVJr#q3ubV5b|VeMN%D4g`M;F?(@`LYv%n*= zn1Ml08H5=tmfDvA1tUCN978H@rJlJh)S$rO8p!74y6eOLc3`N-})te84qb z@G-l_!*s_hiqB(?xH5%=F6Z2{$~)qU^bW@D^{a$eH0JDH#?e00lV$%}mI?P5DjAPI axX&5zh-LK~n-2@J$5m^KK}lJfz}CIx|E|;I{m}&d4|hsP)H z*?xI_OM$$9IG=Xq>$_Sd0;G_Dh+ikaWwDTW2qBqQM!8J?-BS~UKnR0e00000NkvXX Hu0mjf2#X*o literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/mimetype/pdf.png b/research/payg-sso-full/img/mimetype/pdf.png new file mode 100644 index 0000000000000000000000000000000000000000..c68ab66ca23e371d9a42fe97132b3b2707cc3271 GIT binary patch literal 665 zcmV;K0%rY*P)9XK@|RWc8>GZGm>x@ zH5w9ZF#H3Cg20A`!U9VYDhjkCK&~M|V}XSiLS^eE7bwLJ2v?J6E_=mQnn;uo&r4j? zoXg$q&idXsyKZ5OlYILoZ{GL4A2Vyc1+clk4$HD0(Do+&y=qFS_bLn#MUi$${>)V> zsLs#ds%&h$=+R-Hp%g+2iUVEOMdk4D5p6BPyI9ex1J5r5%eFZQ2?3!`=n-tHF1xsh zMx%kbnHfA>TYF6IBNEmkRuhP>(I!g}hIm2n2_3>u!qC|nYPDL@$9A>)gv?XjLXgTT zG8x?HcJXm!1nT4j%J`)aa2!Xslh5a|@48+rCIV9`XAMV3(Qh^}Fg=~Lz;-}NEkc9V zq#z6}0$Ye~s$_e79PM%$*B2I$ot#A1h+Lw|(js9HSOm5Z7pB+T>?{hU60S^50dxcR zc6V`mbybUGY&#LLe+!6MK>DW4`&(Q1ytjuh2M73Cuj5CnrLU6{2qLivFPm&Y0`Uwa zXJEV@9@dV?3{{zZ&j`R&VpAI=U?l<+P^LjHD??H#GUM*jQX-%$;1>G*KNV2$%7`PuA-$J^D{Xzlm!~}bF9?r%jZO!8Xl?@}p{%@FcthwgqeP)BYn@qr{iONmZMGao9AVdGFgNOEWkr!NE)EzYb49D z%waBP%@K;UjhsOQF0C2>F)hB00000NkvXXu0mjf82Tml literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/mimetype/powerpoint.png b/research/payg-sso-full/img/mimetype/powerpoint.png new file mode 100644 index 0000000000000000000000000000000000000000..134a00719753d9014402d33cd5aca2ad29ccc708 GIT binary patch literal 692 zcmV;l0!#ggP)sNhLN#DYidr7guD{6W2V@?44a`HgX z0enAo55-~;7Y7G%c4TCT;CCdfMMU{_U$||o*fi&Fclxn(KLuaszHAk}&mf$za+-wU_&5%bsg>p;uCLmKCJ%rv9=%?$w~D#3H81YaR>{ua#6 zK6*N-J%2OKaf3)K5~obqD-s}M&rPhsGz40cd(e9G#UC%gILD28?MybQ7wY#Cd{2Ft zJ(p}c2UhQiNFXY~^P&zZpo(K4k6*$fcbGRKp a1sDK3SSC8rrcdtx0000?NMQuI$%XBm_0YSAWUl019yy zctjR6F!(8eFr!%Q%zHpVmUKs7M+SzC{oH>NS%Lg{o-U3d6}OTTBzzv&3tI4W@D@lp za0nQ+EMPo8&-SoE3+G)CH#fIA5-jKD+w(69W7;TnLO@LC+<}5ypP!#U_~rC;{fVuj z4lHeq2D1wq@9r*N{Ndv+hP%(q^Y0}{cx>VhTNmSbgLOwv-S>C0PxWRPCbQ)+JD4#) zmRf%H{r&yN-!o}yYO)0}Zem>LkmJ&HuV3N#!fJ^rHdi}L7@n**XK>=4wCvsXodgn-n^H-v?pEGCfTrqMXg;h%ftpr&F|6X%|{|Ua2<@9|lrSCzq zx2x*or-_}nC*o7(4F|60!F7Fjo)1pum0K?0=G@X*+6q4Ij*o#&jGRx+lPlip${jsH z3?1KtZ-q4s4<5v5^7%NqXURTtT-sGP{^Z)pmYPqWdj=r{R(}+6_wh>%9SGb=WxhP1 z(3m2qlpSQ>uVM1)0!D}T6O$81z;RvI&==cBukjJ-31Rj_In%g6tE@YSMY~Wf zyGR_{1>foy!p*65sB{Eoem5Z=_0{Tw$8UDZ{q+(N;P zl??^5^xJ`LdoVPC`PX?I?%j?wVLu`JIWDEv?1`o^foC+&4F!hK@M7UB4)tzR*iYC{ zpiw=Ouo7Jte?Os8a!8eq=_@Cix6DkPQpo;VTo8$`NVpeU6-ax-O~(fAw48&!{;-lw zv!zH>AGZ?F&kS1K649fb*Kb`+jF)U%eHRZPPa^MY#ZXuy@Hcy420tS@&{1QhC?|+I z^365*s3V}4)m7Td9hEwU5lx0Z+ zmSG}j7zmms+Q~ZFOoZA3=(GX|7&HQut7@p02f`u?7grVwXC|j#;XhU}pDS<;ne#`0 Z0RT5E3{AZ4g604K002ovPDHLkV1oSkG^+pr literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/minus.gif b/research/payg-sso-full/img/minus.gif new file mode 100644 index 0000000000000000000000000000000000000000..f4b28bdad850b8bc1d14527a54daafd1be060a42 GIT binary patch literal 71 zcmZ?wbh9u|?2G`n-=(f|Md>o5QTNSuL5p`~BrwC*#dp4>~U&G&vY Y3aYq0Xp{+$yRm%Ps?tuQ00stY01YV@`2YX_ literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/new.gif b/research/payg-sso-full/img/new.gif new file mode 100644 index 0000000000000000000000000000000000000000..754b627e6413f31e6bd600b98c3664b6535b9982 GIT binary patch literal 71 zcmZ?wbhEHbODlK=n! literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/ok.png b/research/payg-sso-full/img/ok.png new file mode 100644 index 0000000000000000000000000000000000000000..a9925a06ab02db30c1e7ead9c701c15bc63145cb GIT binary patch literal 537 zcmV+!0_OdRP)Hs{AQG2a)rMyf zFQK~pm1x3+7!nu%-M`k}``c>^00{o_1pjWJUTfl8mg=3qGEl8H@}^@w`VUx0_$uy4 z2FhRqKX}xI*?Tv1DJd8z#F#0c%*~rM30HE1@2o5m~}ZyoWhqv>ql{V z1ZGE0lgcoK^lx+eqc*rAX1Ky;Xx3U%u#zG!m-;eD1Qsn@kf3|F9qz~|95=&g3(7!X zB}JAT>RU;a%vaNOGnJ%e1=K6eAh43c(QN8RQ6~GP%O}Jju$~Ld*%`mO1p!oXN}Ho}{#R ze}{U4l#!RAnVzuE(dMzWzOb^otgp>^fSb+H*N2Uy($(C=$I2?- zED&bABe8QUkRe&(8c`CQpH@mmtT}V`<;yxP|-s`Z)*kuswM1v*6$X>j??%49BB=5p+xzkEsI~2WEyZN-+An6{Myb!V`~Cb9 zwqGhoQ@uamx$skiOM#2@!9R__b`ccgOdSC;9wZfnNMC$&ckeX~3& qKJy^+KBt4*uRO5bbG@SHp!|{i=br*pdrg7fWbkzLb6Mw<&;$VK?T)|z literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/portlet_dot.gif b/research/payg-sso-full/img/portlet_dot.gif new file mode 100644 index 0000000000000000000000000000000000000000..7e2f4cbbd5f9a50c6cfb5737e41bdeddff055b48 GIT binary patch literal 346 zcmV-g0j2&&Nk%w1VHyA#0K^sm=2!s!v~>T1761PJ_@Y|yl}P`PFZOT&{_x`ei6j2f zuJUdG|9J)e%AWdS0RNUe|ArjxdKdh20PJi4|G9ksjw}9r3;k>W{H|^Pg(m;Kg#VyV z>tX=^lQsHo7XHAFEC2ui02%-p000Hw;GktsX`U#W1R_zTFx+h#^mcfz@B3pwyr6Jr zs2Gn(ToK8vESpD&AW@-0jft#w%k6R@;BZ)Ap(r4dig+y*xZeVZMba2h1dKR*&v(x$ z19lP?eSQ{)h=&XkECUE15*K8Nl$DWyfdc^<77UdPprN317nqqC7ZReN60NSSi=~;G z8Lzgtt{07u7Y>WKz`czD4ynM$y>%EK4#&>D7zz>&q`(K)*xB0K+6&&_;0NF0;N=VC s=HA!o<>>71<{TUo^!4`l`1BkF5%c-~_Bcc+Fn|C6fCwi5AQ%DwJE)VSzW@LL literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/redmult.png b/research/payg-sso-full/img/redmult.png new file mode 100644 index 0000000000000000000000000000000000000000..877be7d16429acee190f76d7cb76e70e9d0fe73b GIT binary patch literal 1000 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uGBwbBK{1_OR83KGlT>pc?zn3rnc6I-I_3Gc1 zD}P+wesgjC-M-_Gi|fA|H~w~Z{bpeJ#lY})%htb}xBQ(v^i*|9{yQmMtuE zS>`SS`X4Bw0mKqN85kUZvum)0~3VD$oR7d$O7qF$H4Gt2ZN7Ac_Wa+SQ6wH z%;50sMjD8dB|mLR|m<|NrmLA0YXsrS;$U z@BjY({nOI&@AvP&OPBuU;QSL6^$)1v-@o4s41c0y{zOIpojCE|!-sz&qkb_k{AOkU z6A}3*GV_&c#&0D+7D(4R28J&c4DMeS^#M7IB|(0{3=Yq3q=7g| z-tI1p|Cw~}0Xdun9+AZi40_5S%viD19u&L_JY5_^DsK7uGYT~s@T?Y zdu-pFX#M-xO&y(&>4|v@B&+T!{$0#{X6-+N=ixJq_slrFFY-nWjEB<5wG8q|kKzxu40~2pg|H{)mwQ&_CQ7;wr7_0$B C91Pe1 literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/sarrow.gif b/research/payg-sso-full/img/sarrow.gif new file mode 100644 index 0000000000000000000000000000000000000000..bafbb1d01f488a1eb7fd1d68d09cee673010cd3a GIT binary patch literal 54 zcmZ?wbhEHbjEB<5wG8q|kKzxu40~2pg|H{)mwQ&_CQ7;wr7_0$B C91Pe1 literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/save.gif b/research/payg-sso-full/img/save.gif new file mode 100644 index 0000000000000000000000000000000000000000..d70866b124207774cb2bfb012ae01147d2ecee25 GIT binary patch literal 103 zcmZ?wbhEHbsai% y!=QNT$CcTe`?@tZ1c+zExZ7n^tQpKmTlOuVbi8fXU?3t ze*OB*n>TOWx^?HyohMJ8Jb(WD<;$1v-@pI(@#CjYpT2zg^7ZT2|2Tl+PZmaY26+Y@ zkWC;v8CdfkwD+WBc5y6Q_ohom(@d60K_d+eQHU$7VI7}Rl#T6&u#aLaU$Ykq`VILv5d=ak|QnQ9Hn@P zj9Ii`@0VnF2%Y5JMHXdv{{sL%LVOUUf7XSbN literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/simple.png b/research/payg-sso-full/img/simple.png new file mode 100644 index 0000000000000000000000000000000000000000..39650091a27174d0ff4759d9d0c5afdcac47ff1e GIT binary patch literal 243 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;jZI zi(`mI@7hU$d`$)dF5lhvaz6@G73h$0`yzC}QN-TRYO>A}&4|m>JmW6+pWCuKcH&aM z1q`wkns=Tn#9G?FX3%@UYiBRv$oeh&+3v#`#hab8_&>X3UVBruZS|bR8Ha1m3QIEo z>S&n8=bP0l+XkKKE+ur literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/svc.jpg b/research/payg-sso-full/img/svc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..db5ec30e3d587c26f348d38cdd7d120c5e7e5802 GIT binary patch literal 99643 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 literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/up.gif b/research/payg-sso-full/img/up.gif new file mode 100644 index 0000000000000000000000000000000000000000..2dbd4e33bdb7067461c7785c3a1cda26f8d70562 GIT binary patch literal 51 zcmZ?wbhEHbWM$xFXkcUjg8%>jEB<6*jSa;(^?zc`(oV|&HrwZqjvu5lqYVC4AubXtsBq) literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/img/xls.gif b/research/payg-sso-full/img/xls.gif new file mode 100644 index 0000000000000000000000000000000000000000..d35e1e4e450d15a60eac4f539e4668b796595eaa GIT binary patch literal 990 zcmZ?wbhEHb`-=F{g{{06sfB*mg4=4;2`1kkx{VTu! z|M~U*_nVJzb0_38_%Qk`bPJgfuU1~DR?Zh3!djAUoR54$nC}dr$WhW zL6bcEyIm6&grzT!O`I2zG%uobe*VfsOMQAAe0v>(CwfHA^o^R~pSCh8Ygt_J=Jbj! zIg8HB`uXpNZ?ApuM7PM9-cd7v$Tx9*P~!ZMqy?dw%VP>RCg-kBDBhTow<@7*OM3a% zjNZHTh!8tZO~ZE35jpw0`*a)}zlfdqs5dhUDrU*^T=O>vrTd z?=9{-T|4nYV;4~Ih357Hl~XUZ&br@kN@6w94MWAwPViJjuj85tavbW!>hSl-!Izo zZsD#k%XfcS-oCo}^q*a)e(x$;62JVx#C<=PANsMjXJhThe{T-_Tygm4>MMT_U;lUf z;oqyT|2|%LaMIO3hd=#&`{w)ezyJTd{rgBGfc@Y9Uyz6aMZ&*-fB*gkMie;4MhU8g zfZ|UUMh1p{1|5)zpgh6Av715Owu?F4XSQ|DH4#OnfCUoFEIg(`3r++I==Arj*eKNM zF-yy@L}k*aloO(i>})C-4ha*vCHTJm*>Q=fnbn=g#D}4&EkHpnglW%&1?(qTg>)v# zJlf>U(ZnudR`N0E1RJ|?bCE-&fxG7n9$A)^3{Tqm`t()bICvDOFfEd7-tu7L!^IAZ zclSz2uGpyBKZoCP+7ph#w6ZE3 J3Y8QXtN~CYWo7^X literal 0 HcmV?d00001 diff --git a/research/payg-sso-full/inc/functions.cfm b/research/payg-sso-full/inc/functions.cfm new file mode 100644 index 0000000..baf398d --- /dev/null +++ b/research/payg-sso-full/inc/functions.cfm @@ -0,0 +1,358 @@ + +/* Все глобальные функции экспортированы в request scope */ +function plain2htm(s) { + return replace(replace(s, chr(13),'',"ALL"),chr(10),'
', "ALL"); +} +request.plain2htm = plain2htm; + +function htm2plain(s) { + return replaceNoCase(s, '
', '#chr(13)##chr(10)#', "ALL"); +} +request.htm2plain = htm2plain; + +function cleanHtm(s) { + return replaceList(s, '<,>,"', '<,>,"'); +} +request.cleanHtm = cleanHtm; + +function clean4CDATA(s) { + LF = chr(10); + return replaceNoCase(replaceList(s, '[,]', '&91;,&93;'),"
",LF,"ALL"); +} +request.clean4CDATA = clean4CDATA; + +function numFmt(num, decimalPlaces = 0){ + var sFormat = ","; + if (decimalPlaces GT 0) {sFormat = sFormat & "." & repeatString("0", decimalPlaces);} + return replace(NumberFormat(num, sFormat), ",", " ", "ALL"); +} +request.numFmt = numFmt; + +function nFmt(num, decimalPlaces = 2){ + if (num EQ 0) return ""; + return numFmt(num, decimalPlaces); +} +request.nFmt = nFmt; + +function dateFmt(date, sFormat = 'YYYY-MM-DD'){ + return dateFormat(date, sFormat); +} +request.dateFmt = dateFmt; + +function dateTimeFmt(date, sDateFormat = 'YYYY-MM-DD', sTimeFormat='HH:MM'){ + return dateFormat(date, sDateFormat) & ' ' & timeFormat(date, sTimeFormat); +} +request.dateTimeFmt = dateTimeFmt; + +function timeFmt(date, sFormat = 'HH:MM'){ + return timeFormat(date, sFormat); +} +request.timeFmt = timeFmt; + +////////////////////////////////////////////////////// +function usrAuthenticated() { + return structKeyExists(request, "auth"); +} +request.usrAuthenticated = usrAuthenticated; +///////////////////////////////////////////////////// + +function filterOn(filter) { + return (isStruct(filter) AND NOT structIsEmpty(filter)); +} +request.filterOn = filterOn; + +function stripWhiteSpace(sNumber) { + return reReplace(sNumber, "[[:space:]]", "", "ALL"); +} +request.stripWhiteSpace = stripWhiteSpace; +/* +// never used +function cleanNumber(sNumber) { + var s = reReplace(sNumber, "[[:space:]]", "", "ALL"); + if ( find(",", s) ) { //watch argument order!!! + // assume Russian format with decimal comma and spaces for thousand separator + return replace(s, ",", "."); + } else { + // assume English format with decimal point and commas for thousand separator + return replace(s, ",", "", "ALL"); + } +} +request.cleanNumber = cleanNumber; +*/ + +/*https://cflib.org/udf/queryColumnToArray*/ +/** + * Takes a selected column of data from a query and converts it into an array. + * + * @param query The query to scan. (Required) + * @param column The name of the column to return data from. (Required) + * @return Returns an array. + * @author Peter J. Farrell (pjf@maestropublishing.com) + * @version 1, July 22, 2005 + */ +function queryColumnToArray(qry, column) { + var arr = arrayNew(1); + var ii = ""; + var loop_len = arguments.qry.recordcount; + for (ii=1; ii lte loop_len; ii=ii+1) { + arrayAppend(arr, arguments.qry[arguments.column][ii]); + } + return arr; +} +request.queryColumnToArray = queryColumnToArray; + +/* ************************************* */ + +function loginPasswordPolicyCheck(usr_id, login, passwd, passwd2) { + msg = ""; + // для старого логина длина не проверяется, все равно ничего не поделаешь + if (NOT(usr_id GT 0) AND len(login) LE 3) { + msg="Слишком короткий логин (минимальная длина логина 3 символа)"; + } else { + if (passwd NEQ passwd2) { + msg="Пароль и подтверждение не совпадают"; + } else { + if (len(passwd) LT "8") msg="Слишком короткий пароль (минимальная длина пароля 8 символов)"; + } + } + return msg; +} +request.loginPasswordPolicyCheck = loginPasswordPolicyCheck; + +function i18(label,label_en=label) { + //примитивная 2-язычная версия + if (request.language EQ 'en') { + return label_en; + } else { + return label; + }; +} +request.i18 = i18; + +function passwordHashCreate(password) { + return GenerateArgon2Hash('#ARGUMENTS.password#', 'argon2id', 1, 16000, 2); +} +request.passwordHashCreate = passwordHashCreate; + +function passwordHashCheck(password, passwordHash) { + return Argon2CheckHash('#ARGUMENTS.password#', ARGUMENTS.passwordHash, 'argon2id'); +} +request.passwordHashCheck = passwordHashCheck; +/* +function skuCode(area_code="", abstract_service_code="") { + var s="#arguments[1]#.#arguments[2]#"; + if (arrayLen(arguments) GE 3) { + if (len(arguments[3]) GT 0) { + s="#s#.#arguments[3]#"; + } else { + s="#s#.0"; + }; + }; + if (arrayLen(arguments) GE 4) { + if (len(arguments[4]) GT 0) { + s="#s#.#arguments[4]#" + } + }; + if (arrayLen(arguments) GE 5) { + var pricingModelSuffix=arguments[5]; + s="#s#-#pricingModelSuffix#"; + } + return s; +} +request.skuCode = skuCode; +*/ +function roundSafe(a, precision) { + return (isNumeric(a) AND isNumeric(precision)) ? round(a,precision) : a; +} +request.roundSafe = roundSafe; + +function timeUnitLabel(n, value=0, locale="ru") { + var labels = ["сек.","мин.","ч.","д.","мес."]; + if (n LE 5 AND n GE 1) {return labels[n];} + else if (n EQ 6) { // в зависимости от числа - "год" г. или "лет" л. + var m = value MOD 100; + if (m GE 11 AND m LE 20) { + return "л."; + } + m = m MOD 10; + if (m GE 1 AND m LE 4) { + return "г."; + } + return "л."; + } + throw (message="timeUnitLabelRu: index out of bounds", detail="Index must be from 1 to 6"); +} +request.timeUnitLabel = timeUnitLabel; + +function dateDiffVerbose(dateFrom, dateTo, maxParts=6, maxPrecision=1, locale="ru") { +// returns formatted datetime interval duration, e.g. 1 hour 5 minutes or 3 years 0 months 12 days +//(currently, only Russian supported) +// +//maxParts specifies, how many parts to display +//maxPrecision starts froms seconds: 1=seconds, 2=minutes, 3=hours, 4=days, 5=months, 6=years +//if maxPrecision specified is greater than given time interval, output is nothing +//locale=ru just for interface, not used +//attention: truncates the tail, not rounds +//example: request.dateDiffVerbose(Now(),Now()+373.1234567, 3, 1) produces 1 г. 0 мес. 8 д. +//example: request.dateDiffVerbose(Now(),Now()+373.1234567, 6, 1) produces 1 г. 0 мес. 8 д. 2 ч. 57 мин. 46 сек. +//intended common usage: request.dateDiffVerbose(dateFrom, dateTo, 2, 1) - prints 2 senior parts of the interval, +//with presision not better than second +// +// this is not the same task as converting number of seconds to days-hours-minutes-seconds, +// because months contain different number of days, and days number of february depends on year + try { + if (NOT (isDate(dateFrom) AND isDate(dateTo))) return ""; + var UNIT_CODES = ["s","n","h","d","m","yyyy"]; + var start = dateFrom; + var finish = dateTo; + + var sOut = ""; + var nUnits = 0; + var nPrintedPositions = 0; + var printStart = false; + + for (i=ArrayLen(UNIT_CODES); i GT 0; i=i-1) { + nUnits = dateDiff(UNIT_CODES[i], start, finish); + start = dateAdd(UNIT_CODES[i], nUnits, start); + if (nPrintedPositions GT 0) {nPrintedPositions=nPrintedPositions+1;} //print started, so increment position + if (nPrintedPositions GT maxParts) {break;} + if (i LT maxPrecision) {break;} + if (nUnits NEQ 0 AND nPrintedPositions EQ 0) {nPrintedPositions=1;} + if (nPrintedPositions GT 0) { + if (len(sOut)) {sOut=sOut & " ";} + sOut=sOut & nUnits & " " & request.timeUnitLabel(i, nUnits, "ru"); + } + } + return sOut; + } catch(e) { + return ""; + } +} +request.dateDiffVerbose = dateDiffVerbose; + +/* +function secondsToDHMS(nSeconds,partsToKeep) { +//format seconds to days-hours-minutes-seconds and truncate to specified precision + { + days = n / (24 * 3600); + + n = n % (24 * 3600); + hours = n / 3600; + + n %= 3600; + minutes = n / 60 ; + + n %= 60; + seconds = n; + + return days & " " & "days " + & hours & " " & "hours " + & minutes & " " & "minutes " + & seconds & " " & "seconds "); + } +} +*/ +/** + * Formats a JSON string with indents and new lines. + * v1.0 by Ben Koshy (modified) + * + * @param str JSON string (Required) + * @return Returns a string of indent-formated JSON + * @author Ben Koshy (cf@animex.com) + * @version 0, September 16, 2012 + */ +// formatJson() :: formats and indents JSON string +// based on blog post @ http://ketanjetty.com/coldfusion/javascript/format-json/ +// modified for CFScript By Ben Koshy @animexcom +// usage: result = formatJson('STRING TO BE FORMATTED') OR result = formatJson(StringVariableToFormat); + +// генерирует html разметку, чтобы не использовать
 и выровнять пробелы
+// содержит ошибку: делает перевод строки после запятой в строке в кавычках
+public string function formatJsonString(str) {
+    var fjson = '';
+    var pos = 0;
+    var strLen = len(arguments.str);
+    var indentStr = '  '; // Adjust Indent Token If you Like (замыкающий пробел - для выравнивания при пробелах после запятой)
+    var newLine = '
'; // Adjust New Line Token If you Like
+ + for (var i=1; i<=strLen; i++) { //fix: <= + var char = mid(arguments.str,i,1); + + if (char == '}' || char == ']') { + fjson &= newLine; + pos = pos - 1; + + for (var j=1; j <= pos; j++) { + fjson &= indentStr; + } + } + + fjson &= char; + + if (char == '{' || char == '[' || char == ',') { + fjson &= newLine; + + if (char == '{' || char == '[') { + pos = pos + 1; + } + + for (var k=1; k <= pos; k++) { + fjson &= indentStr; + } + } + } + + return fjson; +} +request.formatJsonString = formatJsonString; +//нужна еще функция, которая сериализует структуру как pretty printed json. См. https://github.com/bennadel/JsonSerializer.cfc (все не совсем просто, например, не заранее не определен формат даты) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/research/payg-sso-full/inc/menu.cfm b/research/payg-sso-full/inc/menu.cfm new file mode 100644 index 0000000..e6938c1 --- /dev/null +++ b/research/payg-sso-full/inc/menu.cfm @@ -0,0 +1,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/index.cfm b/research/payg-sso-full/index.cfm new file mode 100644 index 0000000..2de843a --- /dev/null +++ b/research/payg-sso-full/index.cfm @@ -0,0 +1,37 @@ + + + + + + + + + + + Отчет по PAYG #request.auth.wz# + + + + + + + + + +

+Подождите пожалуйста, формирование отчета может занять некоторое время +

+
Если автоматического перенаправления не произошло, перейдите по ссылке + + + + + + + + diff --git a/research/payg-sso-full/js/jquery.min.js b/research/payg-sso-full/js/jquery.min.js new file mode 100644 index 0000000..ee02337 --- /dev/null +++ b/research/payg-sso-full/js/jquery.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7.1 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
"+""+"
",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
t
",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; +f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() +{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/research/payg-sso-full/js/jquery.searchabledropdown.js b/research/payg-sso-full/js/jquery.searchabledropdown.js new file mode 100644 index 0000000..0ffa594 --- /dev/null +++ b/research/payg-sso-full/js/jquery.searchabledropdown.js @@ -0,0 +1,3 @@ +/* JQuery Searchable DropDown Plugin | Copyright (c) 2012 xhaggi */ +/*modidfed 14.11.2016|18.01.2018 by msyu - display:inline-block, padding-top: 0 for chrome; BUG: maxListSize IS IGNORED, use instead maxMultiMatch; chrome highlighted position correction;*/ +(function($){var B=register("searchable");B.defaults={maxListSize:100,maxMultiMatch:50,exactMatch:false,wildcards:true,ignoreCase:true,warnMultiMatch:"top {0} matches ...",warnNoMatch:"no matches ...",latency:200,zIndex:"auto"};B.execute=function(g,h){var j=null;var k=null;var l=null;if($.browser.msie&&parseInt(jQuery.browser.version)<7)return this;if(this.nodeName!="SELECT"||this.size>1)return this;var m=$(this);var n={index:-1,options:null};var o="lang";var p=false;$.browser.chrome=/chrome/.test(navigator.userAgent.toLowerCase());if($.browser.chrome)$.browser.safari=false;if($.meta){g=$.extend({},options,m.data())}var q=$("
");var r=$("
");var t=$("");var u=$("
\ No newline at end of file diff --git a/research/payg-sso-full/layout/grid_summary.cfm b/research/payg-sso-full/layout/grid_summary.cfm new file mode 100644 index 0000000..cc56219 --- /dev/null +++ b/research/payg-sso-full/layout/grid_summary.cfm @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
 
+
+ + + Выбрано #ATTRIBUTES.recordCount# + + из #ATTRIBUTES.totalCount# + + + + + + + + + + +
+
+ #paginator.links# +
+
+
+
+ + + + +
+ #paginator.links# +
+
+
+
+ + diff --git a/research/payg-sso-full/layout/json.cfm b/research/payg-sso-full/layout/json.cfm new file mode 100644 index 0000000..47ebf3b --- /dev/null +++ b/research/payg-sso-full/layout/json.cfm @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + ---> + + + + + + + + + + + + + [{"#listGetAt(#columnsOut#,i)#":"#qry[listGetAt(#columnsIn#,i)]#",},] + ---> + + + + + + + + + + + + + + + //copy fields to structure, renaming fields, this preserves data type + + + + + + + + + + + + + + + + + + + +#query2json(ATTRIBUTES.qRead,ATTRIBUTES.convertSnakeToCamel)# + \ No newline at end of file diff --git a/research/payg-sso-full/layout/language_switch.cfm b/research/payg-sso-full/layout/language_switch.cfm new file mode 100644 index 0000000..6533051 --- /dev/null +++ b/research/payg-sso-full/layout/language_switch.cfm @@ -0,0 +1,9 @@ + + +   +   +   + style="font-weight:bold;">Ru + style="font-weight:bold;">En + + \ No newline at end of file diff --git a/research/payg-sso-full/layout/page.cfm b/research/payg-sso-full/layout/page.cfm new file mode 100644 index 0000000..5b43472 --- /dev/null +++ b/research/payg-sso-full/layout/page.cfm @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---> + + + + + + + + + + + + +<cfoutput>#pageTitle#</cfoutput> + + + + + + + + ---> + + + + + + + + + + +
+
+ + +
+ + + +
enctype="#ATTRIBUTES.pageInfo.formEncType#"> +
+
+ +
+
+ + + + +
+ #title# +
+
+ #controls# +
+
+
+ +
+ + + + #ATTRIBUTES.pageInfo.status.errorMessage# + + + + + + + + + + +
+ + +
+ + + +
+ + + + + +
diff --git a/research/payg-sso-full/layout/render_query.cfm b/research/payg-sso-full/layout/render_query.cfm new file mode 100644 index 0000000..1cacb9d --- /dev/null +++ b/research/payg-sso-full/layout/render_query.cfm @@ -0,0 +1,19 @@ + + +
+ + + + + + + + + + + + + + +
#col#
#ATTRIBUTES.query[col]#
+ \ No newline at end of file diff --git a/research/payg-sso-full/layout/xls.cfm b/research/payg-sso-full/layout/xls.cfm new file mode 100644 index 0000000..5d8a964 --- /dev/null +++ b/research/payg-sso-full/layout/xls.cfm @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#title##fieldArray[i]#
#dateFormat(data,'YYYY-MM-DD')# #timeFormat(data,'HH:mm')##Replace(data, '.', ',')##data##data#
+
+
+ + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/layout/xlshtm.cfm b/research/payg-sso-full/layout/xlshtm.cfm new file mode 100644 index 0000000..b74ad64 --- /dev/null +++ b/research/payg-sso-full/layout/xlshtm.cfm @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#structFind(ATTRIBUTES.titleMap,field).title#
+ #ATTRIBUTES.qRead[field]# +
+ + +
+
+ + + + \ No newline at end of file diff --git a/research/payg-sso-full/layout/xml.cfm b/research/payg-sso-full/layout/xml.cfm new file mode 100644 index 0000000..65e7e41 --- /dev/null +++ b/research/payg-sso-full/layout/xml.cfm @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + xls-generator + + + + + + + + + + + + + + + ss:ExpandedColumnCount="#ListLen(qRead.ColumnList)#" + + ss:ExpandedRowCount="#(qRead.RecordCount + 1)#" + x:FullColumns="1" + x:FullRows="1"> + + + + + + + + + + + + + + + + + + select coalesce(max(length(#field#)),0) as maxlen from qRead + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #columns[i].title# + + + + + + + ss:StyleID="DateTime">#dateFormat(qRead[field],"YYYY-MM-DD")#T#timeFormat(qRead[field],"HH:mm:ss.l")##qRead[field]#
+ +
+ +
+ +
+ + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/ac.cfm b/research/payg-sso-full/lib/ac.cfm new file mode 100644 index 0000000..823d1cb --- /dev/null +++ b/research/payg-sso-full/lib/ac.cfm @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select coalesce(max(permission),0) as permission + from usr_role ur + join acl on acl.role_id=ur.role_id + where ur.usr_id= + and acl.obj in () + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/contenttype_icon.cfm b/research/payg-sso-full/lib/contenttype_icon.cfm new file mode 100644 index 0000000..1f8f3b1 --- /dev/null +++ b/research/payg-sso-full/lib/contenttype_icon.cfm @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/checkbox.cfm b/research/payg-sso-full/lib/controls/checkbox.cfm new file mode 100644 index 0000000..38ec2e2 --- /dev/null +++ b/research/payg-sso-full/lib/controls/checkbox.cfm @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + id=#ATTRIBUTES.id# value="#ATTRIBUTES.value#" checked="checked" disabled="disabled" #attr#="#structFind(ATTRIBUTES,attr)#"/> \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/column.cfm b/research/payg-sso-full/lib/controls/column.cfm new file mode 100644 index 0000000..47cf2d8 --- /dev/null +++ b/research/payg-sso-full/lib/controls/column.cfm @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/column_head.cfm b/research/payg-sso-full/lib/controls/column_head.cfm new file mode 100644 index 0000000..f189b06 --- /dev/null +++ b/research/payg-sso-full/lib/controls/column_head.cfm @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#ATTRIBUTES.title# + \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/combo.cfm b/research/payg-sso-full/lib/controls/combo.cfm new file mode 100644 index 0000000..13e2832 --- /dev/null +++ b/research/payg-sso-full/lib/controls/combo.cfm @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (isArray(sel)) { + for(i=1; i <= ArrayLen(sel); i++){ + if (sel[i]==key) {return true;} + } + return false; + } else { //считаем, что из сложных типов тут бывает только массив + if (!isSimpleValue(sel)) {return false;} + /*return (sel == key);*/ + return listFind(sel,key); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #preserveSingleQuotes(ATTRIBUTES.queryString)# + + + + + + + + + + + + + + + + + + + + + + select * from qSel where #ATTRIBUTES.key# in (#selectedList#)1=0 + + + +
#attr#="#structFind(ATTRIBUTES,attr)#"> + +
#Evaluate(ATTRIBUTES.display)#
+
+ + +     + +     +
+
+
+ + + + + +
+ +
+ + + diff --git a/research/payg-sso-full/lib/controls/date.cfm b/research/payg-sso-full/lib/controls/date.cfm new file mode 100644 index 0000000..b6a3f6f --- /dev/null +++ b/research/payg-sso-full/lib/controls/date.cfm @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + id=#ATTRIBUTES.id# value="#dateFormat(value, ATTRIBUTES.format)#" size="#ATTRIBUTES.size#" disabled="disabled" #attr#="#structFind(ATTRIBUTES,attr)#"/> \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/datetime.cfm b/research/payg-sso-full/lib/controls/datetime.cfm new file mode 100644 index 0000000..5b1f4fa --- /dev/null +++ b/research/payg-sso-full/lib/controls/datetime.cfm @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + id=#ATTRIBUTES.id# value="#value#" size="#ATTRIBUTES.size#" disabled="disabled" #attr#="#structFind(ATTRIBUTES,attr)#"/> \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/detail_buttons.cfm b/research/payg-sso-full/lib/controls/detail_buttons.cfm new file mode 100644 index 0000000..1484050 --- /dev/null +++ b/research/payg-sso-full/lib/controls/detail_buttons.cfm @@ -0,0 +1,18 @@ + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/grid_head.cfm b/research/payg-sso-full/lib/controls/grid_head.cfm new file mode 100644 index 0000000..55090e8 --- /dev/null +++ b/research/payg-sso-full/lib/controls/grid_head.cfm @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/link_add.cfm b/research/payg-sso-full/lib/controls/link_add.cfm new file mode 100644 index 0000000..b6fbf5b --- /dev/null +++ b/research/payg-sso-full/lib/controls/link_add.cfm @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/link_del.cfm b/research/payg-sso-full/lib/controls/link_del.cfm new file mode 100644 index 0000000..bd911e9 --- /dev/null +++ b/research/payg-sso-full/lib/controls/link_del.cfm @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/link_edit.cfm b/research/payg-sso-full/lib/controls/link_edit.cfm new file mode 100644 index 0000000..eccea83 --- /dev/null +++ b/research/payg-sso-full/lib/controls/link_edit.cfm @@ -0,0 +1,9 @@ + + + + + + + + +title="#ATTRIBUTES.title_edit#" class="edit"title="#ATTRIBUTES.title_view#" class="view"> \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/link_view.cfm b/research/payg-sso-full/lib/controls/link_view.cfm new file mode 100644 index 0000000..4cf9e70 --- /dev/null +++ b/research/payg-sso-full/lib/controls/link_view.cfm @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/link_view_edit.cfm b/research/payg-sso-full/lib/controls/link_view_edit.cfm new file mode 100644 index 0000000..e676a5a --- /dev/null +++ b/research/payg-sso-full/lib/controls/link_view_edit.cfm @@ -0,0 +1,9 @@ + + + + + + + + +title="#ATTRIBUTES.title_edit#" class="edit"title="#ATTRIBUTES.title_view#" class="view"> \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/menu_item.cfm b/research/payg-sso-full/lib/controls/menu_item.cfm new file mode 100644 index 0000000..6c4a45d --- /dev/null +++ b/research/payg-sso-full/lib/controls/menu_item.cfm @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + +
  • #ATTRIBUTES.label#
  • +
  • #ATTRIBUTES.label#
  • \ No newline at end of file diff --git a/research/payg-sso-full/lib/controls/nowbutton.cfm b/research/payg-sso-full/lib/controls/nowbutton.cfm new file mode 100644 index 0000000..a142ece --- /dev/null +++ b/research/payg-sso-full/lib/controls/nowbutton.cfm @@ -0,0 +1,6 @@ + + + + + + + + + + + + + + + + + + + + + + + #markup# + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/data/del_condition.cfm b/research/payg-sso-full/lib/data/del_condition.cfm new file mode 100644 index 0000000..5cae40c --- /dev/null +++ b/research/payg-sso-full/lib/data/del_condition.cfm @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/data/dep_field.cfm b/research/payg-sso-full/lib/data/dep_field.cfm new file mode 100644 index 0000000..0d065da --- /dev/null +++ b/research/payg-sso-full/lib/data/dep_field.cfm @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/data/dep_param.cfm b/research/payg-sso-full/lib/data/dep_param.cfm new file mode 100644 index 0000000..7084ec2 --- /dev/null +++ b/research/payg-sso-full/lib/data/dep_param.cfm @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/data/dependency.cfm b/research/payg-sso-full/lib/data/dependency.cfm new file mode 100644 index 0000000..19322dc --- /dev/null +++ b/research/payg-sso-full/lib/data/dependency.cfm @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select + + + , #field.expression# + + from + + #from.expression# + + where + + + AND + #condition.expression#= + + order by + + + , #order.expression# + + + + + + diff --git a/research/payg-sso-full/lib/data/dependency_condition.cfm b/research/payg-sso-full/lib/data/dependency_condition.cfm new file mode 100644 index 0000000..1b668ba --- /dev/null +++ b/research/payg-sso-full/lib/data/dependency_condition.cfm @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/data/dependency_field.cfm b/research/payg-sso-full/lib/data/dependency_field.cfm new file mode 100644 index 0000000..4a3c282 --- /dev/null +++ b/research/payg-sso-full/lib/data/dependency_field.cfm @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/research/payg-sso-full/lib/data/dependency_from.cfm b/research/payg-sso-full/lib/data/dependency_from.cfm new file mode 100644 index 0000000..83fbd4f --- /dev/null +++ b/research/payg-sso-full/lib/data/dependency_from.cfm @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/data/dependency_order_by.cfm b/research/payg-sso-full/lib/data/dependency_order_by.cfm new file mode 100644 index 0000000..48b990d --- /dev/null +++ b/research/payg-sso-full/lib/data/dependency_order_by.cfm @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/data/field.cfm b/research/payg-sso-full/lib/data/field.cfm new file mode 100644 index 0000000..8fa07da --- /dev/null +++ b/research/payg-sso-full/lib/data/field.cfm @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/data/field_set.cfm b/research/payg-sso-full/lib/data/field_set.cfm new file mode 100644 index 0000000..b990b40 --- /dev/null +++ b/research/payg-sso-full/lib/data/field_set.cfm @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/data/param.cfm b/research/payg-sso-full/lib/data/param.cfm new file mode 100644 index 0000000..2433014 --- /dev/null +++ b/research/payg-sso-full/lib/data/param.cfm @@ -0,0 +1,354 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/research/payg-sso-full/lib/data/status.cfc b/research/payg-sso-full/lib/data/status.cfc new file mode 100644 index 0000000..6e956c5 --- /dev/null +++ b/research/payg-sso-full/lib/data/status.cfc @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/data/submit_collection.cfm b/research/payg-sso-full/lib/data/submit_collection.cfm new file mode 100644 index 0000000..bc1c10b --- /dev/null +++ b/research/payg-sso-full/lib/data/submit_collection.cfm @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/research/payg-sso-full/lib/data/submit_param.cfm b/research/payg-sso-full/lib/data/submit_param.cfm new file mode 100644 index 0000000..799a3ec --- /dev/null +++ b/research/payg-sso-full/lib/data/submit_param.cfm @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/detail_page_info.cfc b/research/payg-sso-full/lib/detail_page_info.cfc new file mode 100644 index 0000000..1a0d1e8 --- /dev/null +++ b/research/payg-sso-full/lib/detail_page_info.cfc @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/dispatch_detail.cfm b/research/payg-sso-full/lib/dispatch_detail.cfm new file mode 100644 index 0000000..30bffcd --- /dev/null +++ b/research/payg-sso-full/lib/dispatch_detail.cfm @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/encodingUtils.cfc b/research/payg-sso-full/lib/encodingUtils.cfc new file mode 100644 index 0000000..0a5cf2f --- /dev/null +++ b/research/payg-sso-full/lib/encodingUtils.cfc @@ -0,0 +1,283 @@ +component { + + public any function init() { + variables.utcBaseDate = createObject( 'java', 'java.util.Date' ).init( javacast( 'int', 0 ) ); + variables.ECParameterSpecCache = { }; + } + + function convertDateToUnixTimestamp( required date dateToConvert ) { + return dateDiff( 's', utcBaseDate, parseDateTime( dateToConvert ) ); + } + + function convertUnixTimestampToDate( required numeric timestamp ) { + return dateAdd( 's', timestamp, utcBaseDate ); + } + + function base64UrlToBinary( base64url ) { + var base64 = base64url.replace( '-', '+', 'all' ).replace( '_', '/', 'all' ); + var padded = base64 & repeatString( '=', 4 - ( len( base64 ) % 4 ) ); + return binaryDecode( padded, 'base64' ); + } + + function binaryToBase64Url( source ) { + return binaryEncode( source, 'base64' ) + .replace( '+', '-', 'all' ) + .replace( '/', '_', 'all' ) + .replace( '=', '', 'all' ); + } + + /** + * The INTEGER encoding for DER consists of a 02 tag a length encoding of the value + * and then a signed, minimum sized, big endian encoding of the encoded number. + * + * - https://stackoverflow.com/questions/54718741/how-to-der-encode-an-ecdsa-signature + */ + function derEncodeIntegerBytes( byteArray ) { + // first remove any padding + for ( var i = 1; i <= arrayLen( byteArray ); i++ ) { + if ( byteArray[ i ] != 0 ) break; + } + var unpadded = arraySlice( byteArray, i ); + + // add sign if negative + if ( unpadded[ 1 ] < 0 ) { + unpadded.prepend( 0 ); + } + + // if len > 127 the length encoding will be wrong, but that won't happen for the supported signature sizes + var derEncoded = [ 2, unpadded.len() ]; + + derEncoded.append( unpadded, true ); + + return derEncoded; + } + + + /** + * The SEQUENCE encoding is simply a tag set to the byte value 30, the + * length encoding and then the concatenation of the two INTEGER + * structures. + * + * https://stackoverflow.com/questions/54718741/how-to-der-encode-an-ecdsa-signature + * + * Also see: + * https://crypto.stackexchange.com/questions/57731/ecdsa-signature-rs-to-asn1-der-encoding-question + */ + function convertP1363ToDER( signature ) { + var split = len( signature ) / 2; + var r = derEncodeIntegerBytes( arraySlice( signature, 1, split ) ); + var s = derEncodeIntegerBytes( arraySlice( signature, split + 1, split ) ); + + var DERSignature = [ 48 ]; + + var length = r.len() + s.len(); + + if ( length > 255 ) { + throw( + type = 'jwtcfml.InvalidSignature', + message = 'Invalid P1363 key.', + detail = 'The P1363 signature is too long.' + ); + } + + /* + The length is simply a single byte if it is smaller than 128 (or hex 80) + of the size. If it is larger then it is two byte: one byte set to 81, + which indicates that one length byte will follow, and one byte + containing the actual value. + + https://stackoverflow.com/questions/54718741/how-to-der-encode-an-ecdsa-signature + */ + if ( length > 127 ) { + DERSignature.append( -127 ); + length -= 256; + } + DERSignature.append( length ); + + DERSignature.append( r, true ); + DERSignature.append( s, true ); + + return javacast( 'byte[]', DERSignature ); + } + + function convertDERtoP1363( required any signature, required string algorithm ) { + // extract the two integers from the DER signature + // assuming a 02 tag byte followed by a single length byte since we should not see + // anything larger in the supported algorithms + var start = 3; + while ( signature[ start ] != 2 ) start++; + var r = arraySlice( signature, start + 2, signature[ start + 1 ] ); + var s = arraySlice( signature, start + 2 + r.len() + 2 ); + + if ( r[ 1 ] == 0 ) r = arraySlice( r, 2 ); + if ( s[ 1 ] == 0 ) s = arraySlice( s, 2 ); + + var lengthMap = { + ES256: 32, + ES384: 48, + ES512: 64 + }; + + var P1363Signature = [ ]; + + for ( var i = 1; i <= lengthMap[ algorithm ] - r.len(); i++ ) P1363Signature.append( 0 ); + P1363Signature.append( r, true ); + + for ( var i = 1; i <= lengthMap[ algorithm ] - s.len(); i++ ) P1363Signature.append( 0 ); + P1363Signature.append( s, true ); + + return javacast( 'byte[]', P1363Signature ); + } + + function parsePEMEncodedKey( required string pemKey ) { + if ( reFind( '^-----BEGIN (RSA|EC) (PARAMETERS|PRIVATE)', pemKey ) ) { + throw( + type = 'jwtcfml.InvalidPrivateKey', + message = 'Invalid private key format.', + detail = 'Please encode your private key in PKCS8 format, e.g.: `openssl pkcs8 -topk8 -nocrypt -in privatekey.pem -out privatekey.pk8' + ) + } + + var binaryKey = binaryDecode( + trim( pemKey ).reReplace( '-----[A-Z\s]+-----', '', 'all' ).reReplace( '[\r\n]', '', 'all' ), + 'base64' + ); + + if ( find( '-----BEGIN CERTIFICATE-----', pemKey ) ) { + var bis = createObject( 'java', 'java.io.ByteArrayInputStream' ).init( binaryKey ); + return createObject( 'java', 'java.security.cert.CertificateFactory' ) + .getInstance( 'X.509' ) + .generateCertificate( bis ) + .getPublicKey(); + } + + if ( find( '-----BEGIN PUBLIC KEY-----', pemKey ) ) { + var publicKeySpec = createObject( 'java', 'java.security.spec.X509EncodedKeySpec' ).init( binaryKey ); + try { + return createObject( 'java', 'java.security.KeyFactory' ) + .getInstance( 'RSA' ) + .generatePublic( publicKeySpec ); + } catch ( any e ) { + } + try { + return createObject( 'java', 'java.security.KeyFactory' ) + .getInstance( 'EC' ) + .generatePublic( publicKeySpec ); + } catch ( any e ) { + } + } + + if ( find( '-----BEGIN PRIVATE KEY-----', pemKey ) ) { + var privateKeySpec = createObject( 'java', 'java.security.spec.PKCS8EncodedKeySpec' ).init( binaryKey ); + try { + return createObject( 'java', 'java.security.KeyFactory' ) + .getInstance( 'RSA' ) + .generatePrivate( privateKeySpec ); + } catch ( any e ) { + } + try { + return createObject( 'java', 'java.security.KeyFactory' ) + .getInstance( 'EC' ) + .generatePrivate( privateKeySpec ); + } catch ( any e ) { + } + } + + throw( + type = 'jwtcfml.InvalidPEMKey', + message = 'Invalid PEM key.', + detail = 'Please ensure you are using an RSA or EC public or private key or certificate.' + ) + } + + function parseJWK( required struct jwk ) { + if ( jwk.kty == 'RSA' ) { + if ( jwk.keyExists( 'd' ) ) { + try { + var bigInts = bigIntegers( jwk, [ 'n', 'e', 'd', 'p', 'q', 'dp', 'dq', 'qi' ] ); + var keySpec = createObject( 'java', 'java.security.spec.RSAPrivateCrtKeySpec' ).init( + bigInts.n, + bigInts.e, + bigInts.d, + bigInts.p, + bigInts.q, + bigInts.dp, + bigInts.dq, + bigInts.qi + ); + var kf = createObject( 'java', 'java.security.KeyFactory' ).getInstance( 'RSA' ); + return kf.generatePrivate( keySpec ); + } catch ( any e ) { + } + + try { + var bigInts = bigIntegers( jwk, [ 'n', 'd' ] ); + var keySpec = createObject( 'java', 'java.security.spec.RSAPrivateKeySpec' ).init( + bigInts.n, + bigInts.d + ); + var kf = createObject( 'java', 'java.security.KeyFactory' ).getInstance( 'RSA' ); + return kf.generatePrivate( keySpec ); + } catch ( any e ) { + } + } else { + try { + var bigInts = bigIntegers( jwk, [ 'n', 'e' ] ); + var ks = createObject( 'java', 'java.security.spec.RSAPublicKeySpec' ).init( bigInts.n, bigInts.e ); + var kf = createObject( 'java', 'java.security.KeyFactory' ).getInstance( 'RSA' ); + return kf.generatePublic( ks ); + } catch ( any e ) { + } + } + } + + if ( jwk.kty == 'EC' ) { + var kf = createObject( 'java', 'java.security.KeyFactory' ).getInstance( 'EC' ); + var ECParameterSpec = getECParameterSpec( jwk.crv ); + + if ( jwk.keyExists( 'd' ) ) { + var bigInts = bigIntegers( jwk, [ 'd' ] ); + var ks = createObject( 'java', 'java.security.spec.ECPrivateKeySpec' ).init( + bigInts.d, + ECParameterSpec + ); + return kf.generatePrivate( ks ); + } else { + var bigInts = bigIntegers( jwk, [ 'x', 'y' ] ); + var ECPoint = createObject( 'java', 'java.security.spec.ECPoint' ).init( bigInts.x, bigInts.y ); + var ks = createObject( 'java', 'java.security.spec.ECPublicKeySpec' ).init( ECPoint, ECParameterSpec ); + return kf.generatePublic( ks ); + } + } + + throw( + type = 'jwtcfml.InvalidJWK', + message = 'Invalid JWK key.', + detail = 'Please ensure you are using an valid JWK RSA or EC public or private key.' + ) + } + + private function bigIntegers( jwk, keys ) { + var bigInts = { }; + for ( var key in keys ) { + bigInts[ key ] = createObject( 'java', 'java.math.BigInteger' ).init( 1, base64UrlToBinary( jwk[ key ] ) ); + } + return bigInts; + } + + private function getECParameterSpec( crv ) { + if ( !variables.ECParameterSpecCache.keyExists( crv ) ) { + var kpg = createObject( 'java', 'java.security.KeyPairGenerator' ).getInstance( 'EC' ); + var ecgp = createObject( 'java', 'java.security.spec.ECGenParameterSpec' ).init( + 'secp#crv.listLast( '-' )#r1' + ); + kpg.initialize( ecgp ); + variables.ECParameterSpecCache[ crv ] = kpg + .generateKeyPair() + .getPublic() + .getParams(); + } + return variables.ECParameterSpecCache[ crv ]; + } + +} diff --git a/research/payg-sso-full/lib/filter_build.cf_ b/research/payg-sso-full/lib/filter_build.cf_ new file mode 100644 index 0000000..146c197 --- /dev/null +++ b/research/payg-sso-full/lib/filter_build.cf_ @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #item# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/filter_build.cfm b/research/payg-sso-full/lib/filter_build.cfm new file mode 100644 index 0000000..fb35c56 --- /dev/null +++ b/research/payg-sso-full/lib/filter_build.cfm @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + AND #listGetAt(fltr.expression,i,"?")##fltr.field# = <> <= < >= > ILIKE NOT ILIKE ILIKE NOT ILIKE IN () = #fltr.field# + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/research/payg-sso-full/lib/filter_page_info.cfc b/research/payg-sso-full/lib/filter_page_info.cfc new file mode 100644 index 0000000..ea82758 --- /dev/null +++ b/research/payg-sso-full/lib/filter_page_info.cfc @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/filter_rebuild.cfm b/research/payg-sso-full/lib/filter_rebuild.cfm new file mode 100644 index 0000000..e69de29 diff --git a/research/payg-sso-full/lib/filter_settings.cfm b/research/payg-sso-full/lib/filter_settings.cfm new file mode 100644 index 0000000..4d6089d --- /dev/null +++ b/research/payg-sso-full/lib/filter_settings.cfm @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/research/payg-sso-full/lib/filterparam.cfm b/research/payg-sso-full/lib/filterparam.cfm new file mode 100644 index 0000000..af5607c --- /dev/null +++ b/research/payg-sso-full/lib/filterparam.cfm @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (!IsSimpleValue(val)){ + if (isArray(val)) { + return (arrayLen(val) == 0); + } + return false; + } + return ((val==def) OR (val=="")); + + + + + + ", ",,,")/> + + diff --git a/research/payg-sso-full/lib/form_page_info.cfc b/research/payg-sso-full/lib/form_page_info.cfc new file mode 100644 index 0000000..5d0d6ac --- /dev/null +++ b/research/payg-sso-full/lib/form_page_info.cfc @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/generic_page_info.cfc b/research/payg-sso-full/lib/generic_page_info.cfc new file mode 100644 index 0000000..08c50d3 --- /dev/null +++ b/research/payg-sso-full/lib/generic_page_info.cfc @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/init_settings.cfm b/research/payg-sso-full/lib/init_settings.cfm new file mode 100644 index 0000000..f51c235 --- /dev/null +++ b/research/payg-sso-full/lib/init_settings.cfm @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/research/payg-sso-full/lib/jwt.cfc b/research/payg-sso-full/lib/jwt.cfc new file mode 100644 index 0000000..e86a066 --- /dev/null +++ b/research/payg-sso-full/lib/jwt.cfc @@ -0,0 +1,262 @@ +component { + + variables.algorithmMap = { + HS256: 'HmacSHA256', + HS384: 'HmacSHA384', + HS512: 'HmacSHA512', + RS256: 'SHA256withRSA', + RS384: 'SHA384withRSA', + RS512: 'SHA512withRSA', + ES256: 'SHA256withECDSA', + ES384: 'SHA384withECDSA', + ES512: 'SHA512withECDSA' + }; + + public any function init() { + variables.encodingUtils = new encodingUtils(); + variables.jss = createObject( 'java', 'java.security.Signature' ); + variables.messageDigest = createObject( 'java', 'java.security.MessageDigest' ); + return this; + } + + public string function encode( + required struct payload, + required any key, + required string algorithm, + struct headers = { } + ) { + if ( !algorithmMap.keyExists( algorithm ) ) { + throw( + type = 'jwtcfml.InvalidAlgorithm', + message = 'Invalid JWT Algorithm.', + detail = 'The passed in algorithm is not supported.' + ); + } + + var header = { }; + header.append( headers ); + header.append( { + 'typ': 'JWT', + 'alg': algorithm + } ); + + var duplicatedPayload = duplicate( payload ); + for ( var claim in [ 'iat', 'exp', 'nbf' ] ) { + if ( duplicatedPayload.keyExists( claim ) && isDate( duplicatedPayload[ claim ] ) ) { + duplicatedPayload[ claim ] = encodingUtils.convertDateToUnixTimestamp( duplicatedPayload[ claim ] ); + } + } + + var stringToSignParts = [ + encodingUtils.binaryToBase64Url( charsetDecode( serializeJSON( header ), 'utf-8' ) ), + encodingUtils.binaryToBase64Url( charsetDecode( serializeJSON( duplicatedPayload ), 'utf-8' ) ) + ]; + var stringToSign = stringToSignParts.toList( '.' ); + + return stringToSign & '.' & encodingUtils.binaryToBase64Url( sign( stringToSign, key, algorithm ) ); + } + + public struct function decode( + required string token, + any key, + any algorithms = [ ], + struct claims = { }, + boolean verify = true + ) { + var parts = listToArray( token, '.' ); + + if ( arrayLen( parts ) != 3 ) { + throw( + type = 'jwtcfml.InvalidToken', + message = 'Invalid JWT.', + detail = 'The passed in token does not have three `.` delimited parts.' + ); + } + + algorithms = isArray( algorithms ) ? algorithms : [ algorithms ]; + + var decoded = { + header: deserializeJSON( charsetEncode( encodingUtils.base64UrlToBinary( parts[ 1 ] ), 'utf-8' ) ), + payload: deserializeJSON( charsetEncode( encodingUtils.base64UrlToBinary( parts[ 2 ] ), 'utf-8' ) ) + }; + + if ( verify ) { + if ( + !algorithms.find( decoded.header.alg ) || + !algorithmMap.keyExists( decoded.header.alg ) + ) { + throw( + type = 'jwtcfml.InvalidAlgorithm', + message = 'Unsupported or invalid algorithm', + detail = 'The passed in token does not have an algorithm declaration or its declared algorithm (#decoded.header.alg#) does not match the specified algorithms of #serializeJSON( algorithms )#.' + ); + } + + var stringToSign = parts[ 1 ] & '.' & parts[ 2 ]; + var signature = encodingUtils.base64UrlToBinary( parts[ 3 ] ); + + if ( + !verifySignature( + stringToSign, + key, + signature, + decoded.header.alg + ) + ) { + throw( + type = 'jwtcfml.InvalidSignature', + message = 'Signature is Invalid', + detail = 'The signature of the passed in token is invalid.' + ); + } + + var baseClaims = { + 'exp': true, + 'nbf': true + }; + baseClaims.append( claims ); + verifyClaims( decoded.payload, baseClaims ); + } + + for ( var claim in [ 'iat', 'exp', 'nbf' ] ) { + if ( decoded.payload.keyExists( claim ) ) { + decoded.payload[ claim ] = encodingUtils.convertUnixTimestampToDate( decoded.payload[ claim ] ); + } + } + + return decoded.payload; + } + + public struct function getHeader( required string token ) { + return deserializeJSON( charsetEncode( encodingUtils.base64UrlToBinary( listFirst( token, '.' ) ), 'utf-8' ) ); + } + + public function parsePEMEncodedKey( required string pemKey ) { + return encodingUtils.parsePEMEncodedKey( pemKey ); + } + + public function parseJWK( required struct jwk ) { + return encodingUtils.parseJWK( jwk ); + } + + private function sign( message, key, algorithm ) { + if ( left( algorithm, 1 ) == 'H' ) { + var sig = binaryDecode( + hmac( + message, + key, + algorithmMap[ algorithm ], + 'utf-8' + ), + 'hex' + ); + } else { + if ( isSimpleValue( key ) ) { + key = encodingUtils.parsePEMEncodedKey( key ); + } else if ( isStruct( key ) ) { + key = encodingUtils.parseJWK( key ); + } + + var jssInstance = variables.jss.getInstance( algorithmMap[ algorithm ] ); + jssInstance.initSign( key ); + jssInstance.update( charsetDecode( message, 'utf-8' ) ); + var sig = jssInstance.sign(); + if ( left( algorithm, 1 ) == 'E' ) { + sig = encodingUtils.convertDERtoP1363( sig, algorithm ); + } + } + return sig; + } + + private function verifySignature( message, key, signature, algorithm ) { + if ( left( algorithm, 1 ) == 'H' ) { + var sig = binaryDecode( + hmac( + message, + key, + algorithmMap[ algorithm ], + 'utf-8' + ), + 'hex' + ); + return MessageDigest.isEqual( signature, sig ); + } + + if ( left( algorithm, 1 ) == 'E' ) { + signature = encodingUtils.convertP1363ToDER( signature ); + } + + if ( isSimpleValue( key ) ) { + key = encodingUtils.parsePEMEncodedKey( key ); + } else if ( isStruct( key ) ) { + key = encodingUtils.parseJWK( key ); + } + + var jssInstance = variables.jss.getInstance( algorithmMap[ algorithm ] ); + jssInstance.initVerify( key ); + jssInstance.update( charsetDecode( message, 'utf-8' ) ); + return jssInstance.verify( signature ); + } + + private function verifyClaims( payload, claims ) { + if ( + structKeyExists( payload, 'exp' ) + && !verifyDateClaim( payload.exp, claims.exp, -1 ) + ) { + throw( + type = 'jwtcfml.ExpiredSignature', + message = 'Token has expired', + detail = 'The passed in token has expired.' + ); + } + + if ( + structKeyExists( payload, 'nbf' ) + && !verifyDateClaim( payload.nbf, claims.nbf, 1 ) + ) { + throw( + type = 'jwtcfml.NotBeforeException', + message = 'Token is not valid', + detail = 'The passed in token has not yet become valid.' + ); + } + + + + if ( structKeyExists( claims, 'iss' ) ) { + if ( !structKeyExists( payload, 'iss' ) || compare( payload.iss, claims.iss ) != 0 ) { + throw( + type = 'jwtcfml.InvalidIssuer', + message = 'Token has an invalid issuer', + detail = 'The passed in token either does not specify an issuer or the claimed issuer is not valid.' + ); + } + } + + if ( structKeyExists( claims, 'aud' ) ) { + var audArray = isArray( claims.aud ) ? claims.aud : [ claims.aud ]; + if ( !structKeyExists( payload, 'aud' ) || !audArray.find( payload.aud ) ) { + throw( + type = 'jwtcfml.InvalidAudience', + message = 'Token has an invalid audience', + detail = 'The passed in token either does not specify an audience or the claimed audience is not valid.' + ); + } + } + } + + private function verifyDateClaim( payloadDate, claim, failState ) { + var pd = encodingUtils.convertUnixTimestampToDate( payloadDate ); + var cd = claim; + if ( !isBoolean( cd ) || cd ) { + if ( isNumeric( cd ) ) { + cd = encodingUtils.convertUnixTimestampToDate( cd ); + } else if ( !isDate( cd ) ) { + cd = now(); + } + return dateCompare( pd, cd ) != failState; + } + return true; + } + +} diff --git a/research/payg-sso-full/lib/location.cfm b/research/payg-sso-full/lib/location.cfm new file mode 100644 index 0000000..06ceafe --- /dev/null +++ b/research/payg-sso-full/lib/location.cfm @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/ls_catch.cfm b/research/payg-sso-full/lib/ls_catch.cfm new file mode 100644 index 0000000..918f958 --- /dev/null +++ b/research/payg-sso-full/lib/ls_catch.cfm @@ -0,0 +1,24 @@ + + + + + + + Ошибка при обращении к базе данных. Возможно, программа некорректно сформировала условия фильтра или сортировки. В качестве временной меры попробуйте сбросить условия фильтра и сортировки. Просьба сообщить об ошибке администратору.
    + #ATTRIBUTES.catch.message#
    + #ATTRIBUTES.catch.detail#
    +
    +
    + + + + + + + + + + + + +
    \ No newline at end of file diff --git a/research/payg-sso-full/lib/ls_page_info.cfc b/research/payg-sso-full/lib/ls_page_info.cfc new file mode 100644 index 0000000..32e352c --- /dev/null +++ b/research/payg-sso-full/lib/ls_page_info.cfc @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/menu_item.cfm b/research/payg-sso-full/lib/menu_item.cfm new file mode 100644 index 0000000..632e78a --- /dev/null +++ b/research/payg-sso-full/lib/menu_item.cfm @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/mimetype_icon.cfm b/research/payg-sso-full/lib/mimetype_icon.cfm new file mode 100644 index 0000000..6128b1a --- /dev/null +++ b/research/payg-sso-full/lib/mimetype_icon.cfm @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/oauth2.cfc b/research/payg-sso-full/lib/oauth2.cfc new file mode 100644 index 0000000..41fa80d --- /dev/null +++ b/research/payg-sso-full/lib/oauth2.cfc @@ -0,0 +1,193 @@ +/** +* @displayname oauth2 +* @output false +* @hint The oauth2 object. +* @author Matt Gifford +* @website https://www.monkehworks.com +* @purpose A ColdFusion Component to manage authentication using the OAuth2 protocol. +**/ +component accessors="true"{ + + property name="client_id" type="string"; + property name="client_secret" type="string"; + property name="authEndpoint" type="string"; + property name="accessTokenEndpoint" type="string"; + property name="redirect_uri" type="string"; + property name="PKCE" type="struct"; + + /** + * I return an initialized oauth2 object instance. + * @client_id The client ID for your application. + * @client_secret The client secret for your application. + * @authEndpoint The URL endpoint that handles the authorisation. + * @accessTokenEndpoint The URL endpoint that handles retrieving the access token. + * @redirect_uri The URL to redirect the user back to following authentication. + **/ + public oauth2 function init( + required string client_id, + required string client_secret, + required string authEndpoint, + required string accessTokenEndpoint, + required string redirect_uri + ){ + setClient_id( arguments.client_id ); + setClient_secret( arguments.client_secret ); + setAuthEndpoint( arguments.authEndpoint ); + setAccessTokenEndpoint( arguments.accessTokenEndpoint ); + setRedirect_uri( arguments.redirect_uri ); + return this; + } + + /** + * I return the URL as a string which we use to redirect the user for authentication. | + * The method will handle the client_id and redirect_uri values for you. Anything else you need to send to the provider in the URL can be sent via the parameters argument. + * @parameters A structure containing key / value pairs of data to be included in the URL string. + **/ + public string function buildRedirectToAuthURL( struct parameters={} ) { + var objAuthBuilder = new utils.authStringBuilder( + authEndpoint = getAuthEndpoint(), + client_id = getClient_id(), + redirect_uri = getRedirect_uri() + ); + return objAuthBuilder.withParams( arguments.parameters ).get(); + } + + /** + * I return an instance of the authStringBuilder class. The actual link string is generated by then calling the .get() method on the class object. + * The method will handle the client_id and redirect_uri values for you. Anything else you need to send to the provider in the URL can be sent via the parameters argument. + * @parameters A structure containing key / value pairs of data to be included in the URL string. + **/ + public authStringBuilder function buildRedirectToAuthURLWithBuilder( struct parameters={} ) { + var objAuthBuilder = new utils.authStringBuilder( + authEndpoint = getAuthEndpoint(), + client_id = getClient_id(), + redirect_uri = getRedirect_uri() + ); + return objAuthBuilder.withParams( arguments.parameters ); + } + + /** + * I make the HTTP request to obtain the access token. + * @code The code returned from the authentication request. + * @formfields An optional array of structs for the provider requirements to add new form fields. + * @headers An optional array of structs to add custom headers to the request if required. + **/ + public struct function makeAccessTokenRequest( + required string code, + array formfields = [], + array headers = [] + ){ + var stuResponse = {}; + var httpService = new http(); + httpService.setMethod( "post" ); + httpService.setCharset( "utf-8" ); + httpService.setUrl( getAccessTokenEndpoint() ); + if( arrayLen( arguments.headers ) ){ + for( var item in arguments.headers ){ + httpService.addParam( type="header", name=item[ 'name' ], value=item[ 'value' ] ); + } + } + httpService.addParam( type="formfield", name="client_id", value=getClient_id() ); + httpService.addParam( type="formfield", name="client_secret", value=getClient_secret() ); + httpService.addParam( type="formfield", name="code", value=arguments.code ); + httpService.addParam( type="formfield", name="redirect_uri", value=getRedirect_uri() ); + httpService.addParam( type="formfield", name="grant_type", value='authorization_code' ); + if( arrayLen( arguments.formfields ) ){ + for( var item in arguments.formfields ){ + httpService.addParam( type="formfield", name=item[ 'name' ], value=item[ 'value' ] ); + } + } + var result = httpService.send().getPrefix(); + if( '200' == result.ResponseHeader[ 'Status_Code' ] ) { + stuResponse.success = true; + stuResponse.content = result.FileContent; + } else { + stuResponse.success = false; + stuResponse.content = result.Statuscode; + } + //dump(var=formfields,label="form fields"); + return stuResponse; + } + + /** + * I make the HTTP request to refresh the access token. + * @refresh_token The refresh_token returned from the accessTokenRequest request. + **/ + public struct function refreshAccessTokenRequest( + required string refresh_token, + array formfields = [], + array headers = [] + ){ + var stuResponse = {}; + var httpService = new http(); + httpService.setMethod( "post" ); + httpService.setCharset( "utf-8" ); + httpService.setUrl( getAccessTokenEndpoint() ); + httpService.addParam( type="header", name="Content-Type", value="application/x-www-form-urlencoded" ); + if( arrayLen( arguments.headers ) ){ + for( var item in arguments.headers ){ + httpService.addParam( type="header", name=item[ 'name' ], value=item[ 'value' ] ); + } + } + httpService.addParam( type="formfield", name="client_id", value=getClient_id() ); + httpService.addParam( type="formfield", name="client_secret", value=getClient_secret() ); + httpService.addParam( type="formfield", name="refresh_token", value=arguments.refresh_token ); + httpService.addParam( type="formfield", name="grant_type", value="refresh_token" ); + if( arrayLen( arguments.formfields ) ){ + for( var item in arguments.formfields ){ + httpService.addParam( type="formfield", name=item[ 'name' ], value=item[ 'value' ] ); + } + } + var result = httpService.send().getPrefix(); + if( '200' == result.ResponseHeader[ 'Status_Code' ] ) { + stuResponse.success = true; + stuResponse.content = result.FileContent; + } else { + stuResponse.success = false; + stuResponse.content = result.Statuscode; + } + return stuResponse; + } + + /** + * I return a string containing any extra URL parameters to concatenate and pass through when authenticating. + * @argScope A structure containing key / value pairs of data to be included in the URL string. + **/ + public string function buildParamString( struct argScope={} ) { + var strURLParam = '?'; + if( structCount( arguments.argScope ) ) { + var intCount = 1; + for( var key in arguments.argScope ) { + if( listLen( strURLParam ) && intCount > 1 ) { + strURLParam = strURLParam & '&'; + } + strURLParam = strURLParam & lcase( key ) & '=' & trim( arguments.argScope[ key ] ); + intCount++; + } + } + return strURLParam; + } + + /** + * Returns the properties as a struct + */ + public struct function getMemento(){ + var result = {}; + for( var thisProp in getMetaData( this ).properties ){ + if( structKeyExists( variables, thisProp[ 'name' ] ) ){ + result[ thisProp[ 'name' ] ] = variables[ thisProp[ 'name' ] ]; + } + } + return result; + } + + /** + * Generates a struct containing the code verifier and code challenge + * values for use with the PKCE extension. + */ + public struct function generatePKCE(){ + var objPKCE = new utils.deps.pkce.pkce(); + return objPKCE.generatePKCE(); + } + +} \ No newline at end of file diff --git a/research/payg-sso-full/lib/order_build.cfm b/research/payg-sso-full/lib/order_build.cfm new file mode 100644 index 0000000..bda0f97 --- /dev/null +++ b/research/payg-sso-full/lib/order_build.cfm @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/prepare_detail.cfm b/research/payg-sso-full/lib/prepare_detail.cfm new file mode 100644 index 0000000..d84a00a --- /dev/null +++ b/research/payg-sso-full/lib/prepare_detail.cfm @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/research/payg-sso-full/lib/prepare_filter.cfm b/research/payg-sso-full/lib/prepare_filter.cfm new file mode 100644 index 0000000..5282f5c --- /dev/null +++ b/research/payg-sso-full/lib/prepare_filter.cfm @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/prepare_form.cfm b/research/payg-sso-full/lib/prepare_form.cfm new file mode 100644 index 0000000..baccc32 --- /dev/null +++ b/research/payg-sso-full/lib/prepare_form.cfm @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/prepare_ls.cfm b/research/payg-sso-full/lib/prepare_ls.cfm new file mode 100644 index 0000000..01a6e05 --- /dev/null +++ b/research/payg-sso-full/lib/prepare_ls.cfm @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/rest_api_helper.cfc b/research/payg-sso-full/lib/rest_api_helper.cfc new file mode 100644 index 0000000..23221d9 --- /dev/null +++ b/research/payg-sso-full/lib/rest_api_helper.cfc @@ -0,0 +1,396 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/settings.cfm b/research/payg-sso-full/lib/settings.cfm new file mode 100644 index 0000000..4d1505a --- /dev/null +++ b/research/payg-sso-full/lib/settings.cfm @@ -0,0 +1,213 @@ + + + + + + +Разрешение конфликта версий при обновлении софта +Конфликт версий: код требует параметр, отсутствующий в сохраненной версии. Например, одна версия фильтра сохранила свои настройки, +а другая, более новая, пытается прочесть несуществующий ключ. +Другой вариант - несуществующее поле (убранное в очередной версии) - этот конфликт проявится только при запросе к БД. +Варианты решения +- создание параметра с дефолтными значениями при запросе (во все запросы добавить значения по умолчанию). Недостаток - возможно создание помойки +- контроль номера версии. Выглядит сложным в сопровождении +*** Возможно, это была плохая идея - разрешить доступ по длинному ключу. Когда доставали и записывали целиком объект, было меньше возможностей для ошибок +---> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select settings from usr where usr_id='#request.usr_id#' + + + + + + Err: + #cfcatch.message# + + + + + + + + + + + + + + + + + + select count(*) as cnt from usr_serrings where usr_id= + + + + + + + insert int usr_settings (usr_id, settings) + values(, ) + + + + update usr_settings + set settings= + where usr_id= + + + + + + + diff --git a/research/payg-sso-full/lib/silent.cfm b/research/payg-sso-full/lib/silent.cfm new file mode 100644 index 0000000..7f2f6f2 --- /dev/null +++ b/research/payg-sso-full/lib/silent.cfm @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/sortparam.cfm b/research/payg-sso-full/lib/sortparam.cfm new file mode 100644 index 0000000..1648d2b --- /dev/null +++ b/research/payg-sso-full/lib/sortparam.cfm @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/track.cfm b/research/payg-sso-full/lib/track.cfm new file mode 100644 index 0000000..169d97d --- /dev/null +++ b/research/payg-sso-full/lib/track.cfm @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/research/payg-sso-full/lib/upload.cfm b/research/payg-sso-full/lib/upload.cfm new file mode 100644 index 0000000..7d9c22e --- /dev/null +++ b/research/payg-sso-full/lib/upload.cfm @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/lib/utils/authStringBuilder.cfc b/research/payg-sso-full/lib/utils/authStringBuilder.cfc new file mode 100644 index 0000000..990f047 --- /dev/null +++ b/research/payg-sso-full/lib/utils/authStringBuilder.cfc @@ -0,0 +1,142 @@ +component { + + property name="authEndpoint" type="string" default=""; + property name="client_id" type="string" default=""; + property name="redirect_uri" type="string" default=""; + property name="response_type" type="string" default="code"; + property name="state" type="string" default=""; + + property name="PKCECodeChallenge" type="string" default=""; + property name="PKCECodeChallengeMethod" type="string" default="S256"; + property name="PKCECodeVerifier" type="string" default=""; + + public authStringBuilder function init( + required string authEndpoint, + required string client_id, + required string redirect_uri, + string response_type = 'code' + ){ + setAuthEndpoint( arguments.authEndpoint ); + setClientId( arguments.client_id ); + setRedirectURI( arguments.redirect_uri ); + setResponseType( arguments.response_type ); + return this; + } + + public void function setAuthEndpoint( required string authEndpoint ){ + variables.authEndpoint = arguments.authEndpoint; + } + + public void function setClientId( required string client_id ){ + variables.params[ 'client_id' ] = arguments.client_id; + } + + public void function setRedirectURI( required string redirect_uri ){ + variables.params[ 'redirect_uri' ] = arguments.redirect_uri; + } + + public void function setResponseType( required string response_type ){ + variables.params[ 'response_type' ] = arguments.response_type; + } + + public void function setPKCECodeChallenge( required string code_challenge ){ + variables.params[ 'code_challenge' ] = arguments.code_challenge; + } + + public void function setPKCECodeChallengeMethod( required string code_challenge_method ){ + variables.params[ 'code_challenge_method' ] = arguments.code_challenge_method; + } + + public void function setPKCECodeVerifier( required string code_verifier ){ + variables.params[ 'code_verifier' ] = arguments.code_verifier; + } + + + + public authStringBuilder function withAuthEndpoint( + required string authEndpoint + ){ + setAuthEndpoint( arguments.authEndpoint ); + return this; + } + + public authStringBuilder function withClientId( + required string client_id + ){ + setClientId( arguments.client_id ); + return this; + } + + public authStringBuilder function withResponseType( + required string response_type + ){ + setResponseType( arguments.response_type ); + return this; + } + + public authStringBuilder function withRedirectURI( + required string redirect_uri + ){ + setRedirectURI( arguments.redirect_uri ); + return this; + } + + public authStringBuilder function withState( + required string state + ){ + variables.params[ 'state' ] = arguments.state; + return this; + } + + public authStringBuilder function withPKCE( + required string code_challenge, + required string code_challenge_method, + required string code_verifier + ){ + setPKCECodeChallenge( arguments.code_challenge ); + setPKCECodeChallengeMethod( arguments.code_challenge_method ); + setPKCECodeVerifier( arguments.code_verifier ); + return this; + } + + public authStringBuilder function withParams( required struct parameters ){ + for( var item in arguments.parameters ){ + variables.params[ item ] = arguments.parameters[ item ]; + } + return this; + } + + + public string function get(){ + var stuParams = duplicate( variables.params ); + structDelete( stuParams, 'code_verifier' ); + return variables.authEndpoint & buildParamString( argScope = stuParams ); + } + + /** + * Returns a struct representation of the params values stored in variables.params. + */ + public struct function paramsMemento(){ + return variables.params; + } + + /** + * I return a string containing any extra URL parameters to concatenate and pass through when authenticating. + * @argScope A structure containing key / value pairs of data to be included in the URL string. + **/ + public string function buildParamString( struct argScope={} ) { + var strURLParam = '?'; + if( structCount( arguments.argScope ) ) { + var intCount = 1; + for( var key in arguments.argScope ) { + if( listLen( strURLParam ) && intCount > 1 ) { + strURLParam = strURLParam & '&'; + } + strURLParam = strURLParam & lcase( key ) & '=' & trim( arguments.argScope[ key ] ); + intCount++; + } + } + return strURLParam; + } + +} \ No newline at end of file diff --git a/research/payg-sso-full/mod/conventions.txt b/research/payg-sso-full/mod/conventions.txt new file mode 100644 index 0000000..c48422e --- /dev/null +++ b/research/payg-sso-full/mod/conventions.txt @@ -0,0 +1,3 @@ +White label + на экране логина предусматривать место для custom текста + Помимо лого, предусматривать custom text \ No newline at end of file diff --git a/research/payg-sso-full/mod/crm_contract.cfm b/research/payg-sso-full/mod/crm_contract.cfm new file mode 100644 index 0000000..0b2fbf1 --- /dev/null +++ b/research/payg-sso-full/mod/crm_contract.cfm @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/mod/payg.cfm b/research/payg-sso-full/mod/payg.cfm new file mode 100644 index 0000000..2ca1bf9 --- /dev/null +++ b/research/payg-sso-full/mod/payg.cfm @@ -0,0 +1,428 @@ + + + + + + + + + + + + + + + + + + + + + + #getTickCount() - request.startTickCount# + + + + + + select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource + + + #getTickCount() - request.startTickCount# + + + + + + select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage + + + + #getTickCount() - request.startTickCount# + + + + + + select max(timestamp_addition) as dt_load from s3billing.bucket_stat + + + #getTickCount() - request.startTickCount# + + + + + + select max(time) as dt_load from s3billing.usage_bucket_by_user + + + #getTickCount() - request.startTickCount# + + + + + + + + + + + +select s.catalogName as svc, s.component, s.fullCode as code, s.measureShort as unit +, s.priceWVat as price, (s.discount + s.serviceDiscount - s.discount*s.serviceDiscount/100) as discount +,s.serviceStart, s.serviceEnd, s.serviceHash, s.serviceCustomName, f.free_tier +from qSpecification s, qFreeTier f +WHERE s.fullCode=f.code + +UNION + +select s.catalogName as svc, s.component, s.fullCode as code, s.measureShort as unit +, s.priceWVat as price, (s.discount + s.serviceDiscount - s.discount*s.serviceDiscount/100) as discount +,s.serviceStart, s.serviceEnd, s.serviceHash, s.serviceCustomName, 0 +from qSpecification s +WHERE s.fullCode NOT IN () + + + + + + + + + + select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name, + case + when vdc.name like '%-v1cl1%' then 'iaas.ngc.i29' + when vdc.name like '%-v1cl2%' then 'iaas.ngc.i31' + when vdc.name like '%-v1cl4%' then 'iaas.ngc.a28' + when vdc.name like '%-v1cl6%' then 'iaas.ngc.i28' + else '['||vdc.name||']' end as code, + sum(cpu_used/cpu_speed)/4. as core_h, + sum(mem_used)/1024/4. as gb_h, + capacity_resource.timestamp::date as dt + from ngcloud_ru.capacity_resource + join ngcloud_ru.vdc on capacity_resource.vdc_id=vdc.id + join ngcloud_ru.tenant on tenant.id=vdc.tenant_id + where tenant.wzcode = + AND capacity_resource.timestamp::date >= + AND capacity_resource.timestamp::date <= + group by tenant.wzcode, vdc.name, capacity_resource.timestamp::date + order by tenant.wzcode, vdc.name, capacity_resource.timestamp::date; + + + + #getTickCount() - request.startTickCount# + + + + + + + select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name, + case + WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29' + WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31' + WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28' + WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28' + ELSE '['||vdc.name||']' END + || CASE + WHEN storage_profile_types.name ILIKE '%-SSD%' THEN '.ssd-m' + WHEN storage_profile_types.name ILIKE '%-SAS' THEN '.sas-m' + WHEN storage_profile_types.name ILIKE '%-SATA' THEN '.sata-m' + ELSE '.['|| storage_profile_types.name ||']' END + as code, + storage_profile_types.name, -- *** это не тип, а профайл + sum("limit")/1024./4 as gb_h_limit, -- 4 потому, что сбор раз в 15 минут + sum(used)/1024./4 as gb_h_used, + capacity_storage.timestamp::date as dt + from ngcloud_ru.capacity_storage + join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id + join ngcloud_ru.tenant on tenant.id=vdc.tenant_id + join ngcloud_ru.storage_profile_types on capacity_storage.storage_profile_types_id=storage_profile_types.id + where tenant.wzcode = + AND capacity_storage.timestamp::date >= + AND capacity_storage.timestamp::date <= + group by tenant.wzcode, vdc.name, storage_profile_types.name, capacity_storage.timestamp::date + order by tenant.wzcode, vdc.name, storage_profile_types.name, capacity_storage.timestamp::date; + + + + + + + select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */ + (sum(bucket_stat.usage_rgw_main_size_actual)/) as vol_B + ,ceil(sum(bucket_stat.usage_rgw_main_size_actual)//1024/1024/1024) as vol_GB + ,greatest(ceil(sum(bucket_stat.usage_rgw_main_size_actual)/ + /1024/1024/1024)- + case when bucket_stat.placement_id = 1 then 1 else 0 end, 0) as vol_GB_free_tier_subtracted /*считается не в точности так, как в функции*/ + ,case + when bucket_stat.placement_id = 1 then 'paas.s3.ceph' + when bucket_stat.placement_id = 2 then 'paas.s3.cphc' + else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code + --,bucket_stat.placement_id + ,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ + ,bucket_stat.timestamp_addition::date as dt + from s3billing.bucket_stat + join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id + join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id + where bucket_stat.placement_id in (1,2) + AND bucket_stat.owner = + AND bucket_stat.timestamp_addition::date >= + AND bucket_stat.timestamp_addition::date <= + group by bucket_stat.owner, bucket_stat.placement_id, bucket_stat.timestamp_addition::date + order by bucket_stat.owner, bucket_stat.placement_id, bucket_stat.timestamp_addition::date; + + + + #getTickCount() - request.startTickCount# + + + + + + + select + sum( + CASE WHEN + (category.name LIKE 'get%' + OR category.name LIKE 'head%' + OR category.name LIKE 'options%' + ) THEN ops ELSE 0 END + ) as get + ,ceil(sum( + CASE WHEN + (category.name LIKE 'get%' + OR category.name LIKE 'head%' + OR category.name LIKE 'options%' + ) THEN ops ELSE 0 END + )/10000) as get_10k + ,greatest(ceil(sum( + CASE WHEN + (category.name LIKE 'get%' + OR category.name LIKE 'head%' + OR category.name LIKE 'options%' + ) THEN ops ELSE 0 END + )/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 10 ELSE 0 END, 0 + ) as get_10k_free_tier_subtracted + + ,sum( + CASE WHEN + (category.name LIKE 'put%' + OR category.name LIKE 'post%' + OR category.name LIKE 'patch%' + OR category.name LIKE 'list%' + ) THEN ops ELSE 0 END + ) as put + ,ceil(sum( + CASE WHEN + (category.name LIKE 'put%' + OR category.name LIKE 'post%' + OR category.name LIKE 'patch%' + OR category.name LIKE 'list%' + ) THEN ops ELSE 0 END + )/10000) as put_10k + ,greatest(ceil(sum( + CASE WHEN + (category.name LIKE 'put%' + OR category.name LIKE 'post%' + OR category.name LIKE 'patch%' + OR category.name LIKE 'list%' + ) THEN ops ELSE 0 END + )/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 1 ELSE 0 END, 0 + ) as put_10k_free_tier_subtracted + + ,(sum(bytes_sent)) as bytes_sent + ,ceil(sum(bytes_sent)/1024/1024/1024) as bytes_sent_GB + ,greatest(ceil(sum(bytes_sent)/1024/1024/1024) - CASE WHEN bucket_info.placement_id = 1 THEN 100 ELSE 0 END, 0 + ) as bytes_sent_GB_free_tier_subtracted + ,case + when bucket_info.placement_id = 1 then 'paas.s3.ceph' + when bucket_info.placement_id = 2 then 'paas.s3.cphc' + else '['|| TO_CHAR(bucket_info.placement_id,'FM9') ||']' end as code --*** зачем делать там ключ bigint + ,bucket_info.placement_id + --category.name, bucket_info.name + ,'WZ'||lpad(user_info.name, 5, '0') as wz + ,usage_bucket_by_user.time::date as dt + from s3billing.usage_bucket_by_user + join s3billing.user_info on usage_bucket_by_user.user_id=user_info.id + join s3billing.category on usage_bucket_by_user.category_id=category.id + join s3billing.bucket_info on usage_bucket_by_user.bucketid=bucket_info.id + join s3billing.placement on bucket_info.placement_id=placement.id + where 1=1 + AND user_info.name = + AND usage_bucket_by_user.time::date >= + AND usage_bucket_by_user.time::date <= + group by user_info.name, bucket_info.placement_id, usage_bucket_by_user.time::date + order by user_info.name, bucket_info.placement_id, usage_bucket_by_user.time::date; + + + + #getTickCount() - request.startTickCount# + + + + + + + select dt, wz, code || '.vcpu-m' as code, core_h as raw_metric, core_h as metric from qComputing + union all + select dt, wz, code || '.ram-m' as code, gb_h as raw_metric, gb_h as metric from qComputing + union all + select dt, wz, code, gb_h_used as raw_metric, gb_h_used as metric from qStorage + union all + select dt, wz, code || '.vol-m', vol_b as raw_metric, vol_gb as metric from qS3Vol + union all + select dt, wz, code || '.get-m', get as raw_metric, get_10k as metric from qS3OpsTrf + union all + select dt, wz, code || '.put-m', put as raw_metric, put_10k as metric from qS3OpsTrf + union all + select dt, wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric from qS3OpsTrf + + order by dt, code + + + + + #getTickCount() - request.startTickCount# + + + + + + + + + + + + + SELECT + + s.code + m.code as m_code + s.svc + s.component + s.unit + s.price*(100-s.discount)/100 as discounted_price + s.price + s.discount + m.raw_metric + m.metric + s.serviceStart + s.serviceEnd + s.serviceHash + s.serviceCustomName + m.dt + s.free_tier + + FROM qSpec as s, qUnifiedMetric as m + WHERE m.wz= + AND s.code=m.code + AND s.serviceStart <= m.dt + AND (m.dt <= s.serviceEnd OR s.serviceEnd IS NULL) + + UNION + SELECT NULL, m.code, NULL, NULL, NULL, NULL, NULL, NULL, m.raw_metric, m.metric, NULL, NULL, NULL, NULL, m.dt, 0 + FROM qUnifiedMetric as m where m.code NOT IN () + + UNION + SELECT s.code, NULL, s.svc, s.component, s.unit, s.price*(100-s.discount)/100, s.price, s.discount, NULL, NULL, s.serviceStart, s.serviceEnd, s.serviceHash, s.serviceCustomName, NULL, 0 + FROM qSpec as s where s.code NOT IN () + + order by m.dt, s.code + + + + SELECT + + code + m_code + svc + component + unit + discounted_price + sum(raw_metric) as raw_metric + sum(metric) as metric + sum(metric) - free_tier as chargeable_metric + (sum(metric) - free_tier)*discounted_price as charge + serviceStart + serviceEnd + serviceHash + serviceCustomName + free_tier + year(dt) as year + month(dt) as month + + from qChargeDaily + group by code, m_code, svc, serviceCustomName, component, unit, discounted_price, serviceStart, ServiceEnd, serviceHash, free_tier, year(dt), month(dt) + order by year(dt), month(dt), code, m_code + + + + + + + + + + + + + + + #getTickCount() - request.startTickCount# + + + + + #getTickCount() - request.startTickCount# + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/mod/payg.cfm.1.bak b/research/payg-sso-full/mod/payg.cfm.1.bak new file mode 100644 index 0000000..57c4604 --- /dev/null +++ b/research/payg-sso-full/mod/payg.cfm.1.bak @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + + + + + + #getTickCount() - request.startTickCount# + + + + + + + + +select catalogName as svc, component, fullCode as code, measureShort as unit +, priceWVat as price, (discount + serviceDiscount - discount*serviceDiscount/100) as discount +,serviceStart, serviceEnd +from qSpecification + + + + + + select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name, + case + when vdc.name like '%-v1cl1%' then 'iaas.ngc.i29' + when vdc.name like '%-v1cl2%' then 'iaas.ngc.i31' + when vdc.name like '%-v1cl4%' then 'iaas.ngc.a28' + when vdc.name like '%-v1cl6%' then 'iaas.ngc.i28' + else '['||vdc.name||']' end as code, + sum(cpu_used/cpu_speed)/4. as core_h, + sum(mem_used)/1024/4. as gb_h + from ngcloud_ru.capacity_resource + join ngcloud_ru.vdc on capacity_resource.vdc_id=vdc.id + join ngcloud_ru.tenant on tenant.id=vdc.tenant_id + where tenant.wzcode = + AND capacity_resource.timestamp >= + AND capacity_resource.timestamp < + group by tenant.wzcode, vdc.name + order by tenant.wzcode, vdc.name; + + + + #getTickCount() - request.startTickCount# + + + + + + select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource + + + + #getTickCount() - request.startTickCount# + + + + + + + + select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name, + case + WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29' + WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31' + WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28' + WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28' + ELSE '['||vdc.name||']' END + || CASE + WHEN storage_profile_types.name ILIKE '%-SSD%' THEN '.ssd-m' + WHEN storage_profile_types.name ILIKE '%-SAS' THEN '.sas-m' + WHEN storage_profile_types.name ILIKE '%-SATA' THEN '.sata-m' + ELSE '.['|| storage_profile_types.name ||']' END + as code, + storage_profile_types.name, -- *** это не тип, а профайл + sum("limit")/1024./4 as gb_h_limit, -- 4 потому, что сбор раз в 15 минут + sum(used)/1024./4 as gb_h_used + from ngcloud_ru.capacity_storage + join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id + join ngcloud_ru.tenant on tenant.id=vdc.tenant_id + join ngcloud_ru.storage_profile_types on capacity_storage.storage_profile_types_id=storage_profile_types.id + where tenant.wzcode = + AND capacity_storage.timestamp >= + AND capacity_storage.timestamp < + group by tenant.wzcode, vdc.name, storage_profile_types.name + order by tenant.wzcode, vdc.name, storage_profile_types.name; + + + select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage + + + + #getTickCount() - request.startTickCount# + + + + + + + + select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */ + (sum(bucket_stat.usage_rgw_main_size_actual)/) as vol_B + ,ceil(sum(bucket_stat.usage_rgw_main_size_actual)//1024/1024/1024) as vol_GB + ,greatest(ceil(sum(bucket_stat.usage_rgw_main_size_actual)/ + /1024/1024/1024)- + case when bucket_stat.placement_id = 1 then 1 else 0 end, 0) as vol_GB_free_tier_subtracted /*считается не в точности так, как в функции*/ + ,case + when bucket_stat.placement_id = 1 then 'paas.s3.ceph' + when bucket_stat.placement_id = 2 then 'paas.s3.cphc' + else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code + --,bucket_stat.placement_id + ,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ + + from s3billing.bucket_stat + join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id + join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id + where bucket_stat.placement_id in (1,2) + AND bucket_stat.owner = + AND bucket_stat.timestamp_addition >= + AND bucket_stat.timestamp_addition < + group by bucket_stat.owner, bucket_stat.placement_id + order by bucket_stat.owner, bucket_stat.placement_id; + + + + #getTickCount() - request.startTickCount# + + + + + + select max(timestamp_addition) as dt_load from s3billing.bucket_stat + + + + #getTickCount() - request.startTickCount# + + + + + +select + sum( + CASE WHEN + (category.name LIKE 'get%' + OR category.name LIKE 'head%' + OR category.name LIKE 'options%' + ) THEN ops ELSE 0 END + ) as get + ,ceil(sum( + CASE WHEN + (category.name LIKE 'get%' + OR category.name LIKE 'head%' + OR category.name LIKE 'options%' + ) THEN ops ELSE 0 END + )/10000) as get_10k + ,greatest(ceil(sum( + CASE WHEN + (category.name LIKE 'get%' + OR category.name LIKE 'head%' + OR category.name LIKE 'options%' + ) THEN ops ELSE 0 END + )/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 10 ELSE 0 END, 0 + ) as get_10k_free_tier_subtracted + + ,sum( + CASE WHEN + (category.name LIKE 'put%' + OR category.name LIKE 'post%' + OR category.name LIKE 'patch%' + OR category.name LIKE 'list%' + ) THEN ops ELSE 0 END + ) as put + ,ceil(sum( + CASE WHEN + (category.name LIKE 'put%' + OR category.name LIKE 'post%' + OR category.name LIKE 'patch%' + OR category.name LIKE 'list%' + ) THEN ops ELSE 0 END + )/10000) as put_10k + ,greatest(ceil(sum( + CASE WHEN + (category.name LIKE 'put%' + OR category.name LIKE 'post%' + OR category.name LIKE 'patch%' + OR category.name LIKE 'list%' + ) THEN ops ELSE 0 END + )/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 1 ELSE 0 END, 0 + ) as put_10k_free_tier_subtracted + + ,(sum(bytes_sent)) as bytes_sent + ,ceil(sum(bytes_sent)/1024/1024/1024) as bytes_sent_GB + ,greatest(ceil(sum(bytes_sent)/1024/1024/1024) - CASE WHEN bucket_info.placement_id = 1 THEN 100 ELSE 0 END, 0 + ) as bytes_sent_GB_free_tier_subtracted + + ,case + when bucket_info.placement_id = 1 then 'paas.s3.ceph' + when bucket_info.placement_id = 2 then 'paas.s3.cphc' + else '['|| TO_CHAR(bucket_info.placement_id,'FM9') ||']' end as code --*** зачем делать там ключ bigint + ,bucket_info.placement_id + --category.name, bucket_info.name + ,'WZ'||lpad(user_info.name, 5, '0') as wz + from s3billing.usage_bucket_by_user + join s3billing.user_info on usage_bucket_by_user.user_id=user_info.id + join s3billing.category on usage_bucket_by_user.category_id=category.id + join s3billing.bucket_info on usage_bucket_by_user.bucketid=bucket_info.id + join s3billing.placement on bucket_info.placement_id=placement.id + where 1=1 + AND user_info.name = + AND usage_bucket_by_user.time >= + AND usage_bucket_by_user.time < + group by user_info.name, bucket_info.placement_id + order by user_info.name, bucket_info.placement_id; + + + + #getTickCount() - request.startTickCount# + + + + + + select max(time) as dt_load from s3billing.usage_bucket_by_user + + + + #getTickCount() - request.startTickCount# + + + + + + +select wz, code || '.vcpu-m' as code, core_h as raw_metric, core_h as metric, core_h as chargeable_metric from qComputing +union all +select wz, code || '.ram-m' as code, gb_h as raw_metric, gb_h as metric, gb_h as chargeable_metric from qComputing +union all +select wz, code, gb_h_used as raw_metric, gb_h_used as metric, gb_h_used as chargeable_metric from qStorage +union all +select wz, code || '.vol-m', vol_b as raw_metric, vol_gb as metric, vol_GB_free_tier_subtracted as chargeable_metric from qS3Vol +union all +select wz, code || '.get-m', get as raw_metric, get_10k as metric, get_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf +union all +select wz, code || '.put-m', put as raw_metric, put_10k as metric, put_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf +union all +select wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric, bytes_sent_gb_free_tier_subtracted as chargeable_metric from qS3OpsTrf + + + + #getTickCount() - request.startTickCount# + + + + + + + + + + + + +SELECT + + s.code + m.code as m_code + s.svc + s.component + m.chargeable_metric + s.unit + s.price*(100-s.discount)/100 as discounted_price + s.price*(100-s.discount)/100*m.chargeable_metric as charge + + + s.price + s.discount + m.raw_metric + m.metric + + + +FROM qSpec as s, qUnifiedMetric as m +WHERE m.wz= AND s.code=m.code +order by s.code + + + + #getTickCount() - request.startTickCount# + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/research/payg-sso-full/payg.cfm b/research/payg-sso-full/payg.cfm new file mode 100644 index 0000000..69140bd --- /dev/null +++ b/research/payg-sso-full/payg.cfm @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + Отчет по PAYG #request.auth.wz# + + + + + + + + + + +
    +Период с +по + + +
    + + + + + + + +Часов в периоде: #hours# Строк в отчете: #report.qCharge.recordCount#
    +Актуальность данных: +VCD Computing: #dateFormat(report.qComputingAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qComputingAge.dt_load,'HH:MM:SS')# +VCD Storage: #dateFormat(report.qStorageAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qStorageAge.dt_load,'HH:MM:SS')# +S3 хранение: #dateFormat(report.qS3VolAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3VolAge.dt_load,'HH:MM:SS')# +S3 операции и трафик: #dateFormat(report.qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3OpsTrfAge.dt_load,'HH:MM:SS')# +Цены GPL
    + +
    + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    АртикулКол-во (метрика) + Оплачиваемый объемЦена ₽ с НДССтоимость ₽ с НДС   УслугаКомпонентЕд.изм.
    #year#-#numberFormat(month,"00")#
    + #svc# + (#serviceCustomName#) + (не найдено в договоре) +
    #currentRow##code# (#m_code#)#metric##chargeable_metric##discounted_price##numberFormat(charge,".00")##svc##component##unit#
    Итого     #svc#:#NumFmt(acc,2)#
    + + + + + + + diff --git a/research/payg-sso-full/style/web.css b/research/payg-sso-full/style/web.css new file mode 100644 index 0000000..3463337 --- /dev/null +++ b/research/payg-sso-full/style/web.css @@ -0,0 +1,321 @@ +/*common elements*/ +html, body { + margin: 0; + padding: 0; + border: none; + height: 100%; +} +body, table, tr, td, th, input, select, textarea, button, form, ul, li, p { + font-size: 11px; + font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; + color:black; +} +form {margin: 0;padding:0;} +p {margin: 0.5em;} +table {border-collapse: collapse;} +img {border: none; margin: 0; vertical-align: middle;} +a, a:link, a:visited {color: #111111; text-decoration: underline;} +a:hover {color: #ff7600; text-decoration: underline;} + + +/* form elements */ +input {color: black; padding: 0 0.3em; } +input:read-only {color:#555; background-color:#f0f0f0;} +input:disabled {color:#555; background-color:#f0f0f0;} +select:disabled {color:#555;} +select option[disabled] { color:#ddd;} + +.detail .td input[type="text"]:disabled {border:1px solid #aaa; color:#555;} +.textbox-disabled {display:inline-block; border: 1px solid #aaa; color:#555; background-color:#f0f0f0; padding:.1em;} + +/*layout*/ + +div.vspacer {height:5px;} + +ul#mainmenu { + list-style-type:none; + padding:0; + margin:0; + display:block; + width:100%; +} +ul#mainmenu li { + text-align:right; + vertical-align:baseline; + padding:.2em 15px .2em 0 ; + margin:.3em 0; + background: url('../img/sarrow.gif') center right no-repeat; + font-size:120%; + font-weight:normal; + font-family: Verdana, Tahoma, Arial, Helvetica, sans-serif; + line-height: 1.1em; +} +ul#mainmenu li a{/*display:block;*/color:#cde;text-decoration:none;} +ul#mainmenu li a:hover{text-decoration:underline;} +ul#mainmenu li.selected {color: /*#4682b4;*/ #fa6 /*#00f*/;} +ul#mainmenu li.menu-item-ext {background: url('../img/external.gif') center right no-repeat;} +ul#mainmenu li.menu-item-noaction {background: none; color: #777;} +ul#mainmenu li.menu-title { + color: #111; + background:none white; + margin:.5em 0 0 0; + /*font-weight: bold;*/ + /*border:1px solid #ccc;*/ +} + +.page {display:table; table-layout: fixed; width:100%; height:100%;} + +.page-main {display:table-row; height:100%;} + +.page-footer {display:table-row; height:1px;} + +.menu {display:table-cell; width:150px; padding:0 0 0 .5em; background-color: #012; -border:1px solid red;} + +.content {display:table-cell; height:100%; vertical-align:top; padding: 3px;} + +.header {display:block; /*background:url('../img/portlet_dot.gif') center left no-repeat; padding-left:33px;*/ line-height: 21px; font-family: Verdana, Tahoma, sans-serif;} + +.control-bar {display:table; width:100%; color:/*#559*/white; /*border:1px solid #ccc;*/ height:19px; } +.header .control-bar a:link, .header .control-bar a:visited {color:white; padding: .2em .5em;} +.header .control-bar a:hover {background:white;color:#f90; padding: .2em .5em;} + +.title {display:table-cell; padding:1px 12px; vertical-align:middle; font-size:110%; background-color:#aaa/*#ccc*//*rgb(117,147,156)*/; /*color:#fa6;*/ border: 1px solid #bbb; border-right:none;} +.title b {color:#026;} + +.main-controls {display:table-cell; padding:0 7px; text-align:right; vertical-align: middle; background-color:#aaa/*rgb(117,147,156)*/; border: 1px solid #bbb; border-left:none;} + +.footer {height:21px; line-height: 21px; background-color:#e0e0e0; border:1px solid #bbb; text-align: right; vertical-align: middle; padding:0 3px;} + + +.table {display:table;} +.tr {display:table-row;} +.td, .th {display:table-cell; padding: 0 0.5em; vertical-align:top;} + + +.detail { + display:table; + width:100%; + margin: 3px 0; + border:1px solid #ddd; + border-collapse: collapse; +} +.detail .tr{ + line-height: 1.5em; +} +.detail .th { + display:table-cell; + text-align:right; + background-color:#e0e0e0; + padding:0.35em 0.5em; + border:none; + /*color: #5f5f5f;*/ + font-weight:normal; + vertical-align:top; + /*border:1px solid red;*/ +} +.detail .td { + display:table-cell; + background-color:#e7e7e7; + padding:0.2em 0.5em; + border:1px solid #ddd; + vertical-align:baseline; +} +.detail .td input, .detail .td select, .detail .td img, .detail .td button, .detail .td div, .detail .td span { + vertical-align: baseline; + margin: 0 0.3em; +} + +.detail .td label { + vertical-align: baseline; + margin: 0 0.3em 0 0; + line-height:normal; +} + +.detail .td input[type="checkbox"] { + vertical-align: top; margin: 0 0 0 0.3em; +} + +/*.detail .td input[type="text"] { + width: 97%; +}*/ + +.detail .td textarea { + color: black; + width: 97%; + margin-left: 0.2em; + padding: 0.2em 0.5em; +} +/***hack*/ +.detail .td a img {vertical-align:text-bottom;} + +.filter {background-color: #f7f7f7;} +.disabled, tr.disabled td, tr.disabled th {color: #888;} +.plate {background-color:#f0f0f0; padding:.1em; border:1px solid #ddd;} + +button, .button, .content a.button:link { + background: #fafafa; + -background: -webkit-linear-gradient(top, #fafafa 0%, #f4f4f4 40%,#e5e5e5 100%); + background:-webkit-linear-gradient(top, #dde 0%, #cde 40%,#bcd 100%); + border: 1px solid #aad; + padding: 1px 10px; + color: #black; + border-radius: 3px; + box-shadow: 0 1px 1px #ddd; + } + +button:disabled, .button:disabled, .maincontrol:disabled { + background: #fafafa; + background: -webkit-linear-gradient(top, #fafafa 0%,#f4f4f4 40%,#e5e5e5 100%); + border-color: #aaa; + color: #999; + box-shadow: none; +} + +button:not(:disabled):hover, +.button:not(:disabled):hover, +.maincontrol:not(:disabled):hover +{ + background: #fefefe; + background: -webkit-linear-gradient(top, #fefefe 0%,#f8f8f8 40%,#e9e9e9 100%); + box-shadow: 0 1px 3px rgba(7, 7, 7, 0.35); + border: 1px solid #aaa; + color: #ff7600; +} + +button:not(:disabled):active, .button:not(:disabled):active { + background: #f4f4f4; + background: -webkit-linear-gradient(top, #f4f4f4 0%,#efefef 40%,#dcdcdc 100%); + box-shadow: inset 0 1px 3px rgba(7, 7, 7, 0.35); +} + +button.maincontrol { + /*background-color:#c3c82f; + background:-webkit-linear-gradient(top, #cd6 0%, #cd6 40%,#bc5 100%);*/ + -background-color:#6fa0f0; + background-color:#6fa0f0; + background:-webkit-linear-gradient(top, #dde 0%, #cde 40%,#bcd 100%); + color: black; +} + +button.maincontrol:hover { + +} + + +/*не совсем аккуратно, при нажатии выглядит чуть иначе, чем кнопка*/ +.content button a, .content button a:link, .content button a:visited {color: #790; text-decoration:none; cursor:default;} +.content button:hover a, .content button:active {color: #ff7600; text-decoration:none; cursor:default;} +.content button.maincontrol a, .content button.maincontrol a:link,.content button.maincontrol a:visited {color: black;} +.content button.maincontrol:hover a, .content button.maincontrol:active a {color: #ff7600;} + +.submitnew { + background-image:url('../img/new.gif'); + width:13px; height:13px; border:none; padding:0; color:transparent; cursor:pointer; +} +.submitsave { + background-image:url('../img/save.gif'); + width:14px; height:14px; border:none; padding:0; color:transparent; cursor:pointer; +} +.submitdel { + background-image:url('../img/del.gif'); + width:13px; height:13px; border:none; padding:0; color:transparent; cursor:pointer; +} +.submitminus { + background-image:url('../img/minus.gif'); + width:13px; height:13px; border:none; padding:0; color:transparent; cursor:pointer; +} + +.content a, .content a:link, .content a:visited {color: #1111ee; text-decoration: none;} +.content a:hover {color: #ff7600; text-decoration: underline;} +.content h4 {margin-block-end: .5em;} +.content i {color:#555;} + +.cell {border: 1px solid #ddd; width:100%; padding: 0.2em;} + +.l, td.l, th.l{text-align: left;} +.r, td.r, th.r{text-align: right;} +.c, td.c, th.c{text-align: center;} +.nw {white-space: nowrap;} +.b {font-weight:bold;} +.i {font-style:italic;} +.wide {min-width:100%} +.wh100 {width:100%; height:100%;} +.table {display:table} +.tcell {display:table-cell} +.mid {vertical-align:middle} /*используется для заполнения ячейки таблицы якорем a href*/ + +.err {color: red;} +.warn {color: #f80;} + +a.up {background: url('../img/up.gif') center right no-repeat; padding-right: 7px;} +a.add {background: url('../img/add.gif') center right no-repeat; width:13px; height:13px; display:inline-block;} +a.edit {background: url('../img/edit.gif') center right no-repeat; width:13px; height:13px; display:inline-block;} +a.view {background: url('../img/view.gif') center right no-repeat; width:13px; height:13px; display:inline-block;} +a.del {background: url('../img/del.gif') center right no-repeat; width:13px; height:13px; display:inline-block;} + + +/* worktable classes */ + +table.worktable {border-collapse:separate; border-spacing:0; border-left:1px solid #ddd;} + +table.worktable th, +table.worktable td { + border-bottom: thin solid #ddd; + border-right: thin solid #ddd; +} +table.worktable thead th, +table.worktable thead td { + box-shadow: 0 -1px 0 0 #ddd; +} +table.worktable thead { + top: 0; + left: 0; + position: sticky; + z-index: 1; +} + +table.worktable td p {margin:0;} + +table.worktable thead tr td, table.worktable tr th{padding: 3px; background-color: #999;} + +table.worktable tr {height: 1.7em; background-color: white;} + +table.worktable tr td {padding:0.1em 0.3em; height:2em;} + +table.worktable tr:hover, table.worktable tr td:hover {background-color:#e5e5e5;} + +table.worktable th {font-weight:500; color:white;} + +/*double borders - not tested with border-collapse:separate*/ +table.worktable tbody tr td.lbd, +table.worktable thead tr td.lbd + {border-left: double #ccc;} + +table.worktable tbody tr td.rbd, +table.worktable thead tr td.rbd + {border-right: double #ccc;} + +table.worktable tbody tr td.tbd, +table.worktable thead tr td.tbd, +table.worktable tbody tr.tbd td, +table.worktable thead tr.tbd td + {border-top: double #ccc;} + +table.worktable tbody tr td.bbd, +table.worktable thead tr td.bbd, +table.worktable tbody tr.bbd td, +table.worktable thead tr.bbd td + {border-bottom: double #ccc;} + +table.worktable tr.hist {background-color: #f6f6f6;} +table.worktable tr.hist:hover, table.worktable tr.hist:hover td, table.worktable tr.comment:hover{background-color:#efefef;} +table.worktable tr.hist td.marked {background: #ddf5c0;} +table.worktable tr.hist:hover td.marked{background-color:#d0f0b9;} + + +@media print { + #mainmenu, .menu, .page-footer, .control-bar, .noprint {display:none;} +} + + +