mirror of https://github.com/portainer/portainer
commit
c1433eff0d
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"plugins": ["lodash", "angularjs-annotate"],
|
||||||
|
"presets": [
|
||||||
|
[
|
||||||
|
"@babel/preset-env",
|
||||||
|
{
|
||||||
|
"modules": false,
|
||||||
|
"useBuiltIns": "usage"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
|
@ -53,6 +53,7 @@ plugins:
|
||||||
mass_threshold: 80
|
mass_threshold: 80
|
||||||
eslint:
|
eslint:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
channel: "eslint-5"
|
||||||
config:
|
config:
|
||||||
config: .eslintrc.yml
|
config: .eslintrc.yml
|
||||||
fixme:
|
fixme:
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
test/
|
549
.eslintrc.yml
549
.eslintrc.yml
|
@ -1,287 +1,292 @@
|
||||||
env:
|
env:
|
||||||
browser: true
|
browser: true
|
||||||
jquery: true
|
jquery: true
|
||||||
|
node: true
|
||||||
|
es6: true
|
||||||
|
|
||||||
|
globals:
|
||||||
|
angular: true
|
||||||
|
__CONFIG_GA_ID: true
|
||||||
|
|
||||||
# globals:
|
|
||||||
# angular: true
|
|
||||||
# $: true
|
|
||||||
# _: true
|
|
||||||
# moment: true
|
|
||||||
# filesize: true
|
|
||||||
# splitargs: true
|
|
||||||
extends:
|
extends:
|
||||||
- 'eslint:recommended'
|
- 'eslint:recommended'
|
||||||
|
|
||||||
# http://eslint.org/docs/rules/
|
parserOptions:
|
||||||
|
ecmaVersion: 2018
|
||||||
|
sourceType: module
|
||||||
|
ecmaFeatures:
|
||||||
|
modules: true
|
||||||
|
|
||||||
|
# # http://eslint.org/docs/rules/
|
||||||
rules:
|
rules:
|
||||||
# Possible Errors
|
# # Possible Errors
|
||||||
no-await-in-loop: off
|
# no-await-in-loop: off
|
||||||
no-cond-assign: error
|
# no-cond-assign: error
|
||||||
no-console: off
|
# no-console: off
|
||||||
no-constant-condition: error
|
# no-constant-condition: error
|
||||||
no-control-regex: error
|
# no-control-regex: error
|
||||||
no-debugger: error
|
# no-debugger: error
|
||||||
no-dupe-args: error
|
# no-dupe-args: error
|
||||||
no-dupe-keys: error
|
# no-dupe-keys: error
|
||||||
no-duplicate-case: error
|
# no-duplicate-case: error
|
||||||
no-empty-character-class: error
|
# no-empty-character-class: error
|
||||||
no-empty: error
|
no-empty: warn
|
||||||
no-ex-assign: error
|
# no-ex-assign: error
|
||||||
no-extra-boolean-cast: error
|
# no-extra-boolean-cast: error
|
||||||
no-extra-parens: off
|
# no-extra-parens: off
|
||||||
no-extra-semi: error
|
# no-extra-semi: error
|
||||||
no-func-assign: error
|
# no-func-assign: error
|
||||||
no-inner-declarations:
|
# no-inner-declarations:
|
||||||
- error
|
# - error
|
||||||
- functions
|
# - functions
|
||||||
no-invalid-regexp: error
|
# no-invalid-regexp: error
|
||||||
no-irregular-whitespace: error
|
# no-irregular-whitespace: error
|
||||||
no-negated-in-lhs: error
|
# no-negated-in-lhs: error
|
||||||
no-obj-calls: error
|
# no-obj-calls: error
|
||||||
no-prototype-builtins: off
|
# no-prototype-builtins: off
|
||||||
no-regex-spaces: error
|
# no-regex-spaces: error
|
||||||
no-sparse-arrays: error
|
# no-sparse-arrays: error
|
||||||
no-template-curly-in-string: off
|
# no-template-curly-in-string: off
|
||||||
no-unexpected-multiline: error
|
# no-unexpected-multiline: error
|
||||||
no-unreachable: error
|
# no-unreachable: error
|
||||||
no-unsafe-finally: off
|
# no-unsafe-finally: off
|
||||||
no-unsafe-negation: off
|
# no-unsafe-negation: off
|
||||||
use-isnan: error
|
# use-isnan: error
|
||||||
valid-jsdoc: off
|
# valid-jsdoc: off
|
||||||
valid-typeof: error
|
# valid-typeof: error
|
||||||
|
|
||||||
# Best Practices
|
# # Best Practices
|
||||||
accessor-pairs: error
|
# accessor-pairs: error
|
||||||
array-callback-return: off
|
# array-callback-return: off
|
||||||
block-scoped-var: off
|
# block-scoped-var: off
|
||||||
class-methods-use-this: off
|
# class-methods-use-this: off
|
||||||
complexity:
|
# complexity:
|
||||||
- error
|
# - error
|
||||||
- 6
|
# - 6
|
||||||
consistent-return: off
|
# consistent-return: off
|
||||||
curly: off
|
# curly: off
|
||||||
default-case: off
|
# default-case: off
|
||||||
dot-location: off
|
# dot-location: off
|
||||||
dot-notation: off
|
# dot-notation: off
|
||||||
eqeqeq: error
|
# eqeqeq: error
|
||||||
guard-for-in: error
|
# guard-for-in: error
|
||||||
no-alert: error
|
# no-alert: error
|
||||||
no-caller: error
|
# no-caller: error
|
||||||
no-case-declarations: error
|
# no-case-declarations: error
|
||||||
no-div-regex: error
|
# no-div-regex: error
|
||||||
no-else-return: off
|
# no-else-return: off
|
||||||
no-empty-function: off
|
no-empty-function: warn
|
||||||
no-empty-pattern: error
|
# no-empty-pattern: error
|
||||||
no-eq-null: error
|
# no-eq-null: error
|
||||||
no-eval: error
|
# no-eval: error
|
||||||
no-extend-native: error
|
# no-extend-native: error
|
||||||
no-extra-bind: error
|
# no-extra-bind: error
|
||||||
no-extra-label: off
|
# no-extra-label: off
|
||||||
no-fallthrough: error
|
# no-fallthrough: error
|
||||||
no-floating-decimal: off
|
# no-floating-decimal: off
|
||||||
no-global-assign: off
|
# no-global-assign: off
|
||||||
no-implicit-coercion: off
|
# no-implicit-coercion: off
|
||||||
no-implied-eval: error
|
# no-implied-eval: error
|
||||||
no-invalid-this: off
|
# no-invalid-this: off
|
||||||
no-iterator: error
|
# no-iterator: error
|
||||||
no-labels:
|
# no-labels:
|
||||||
- error
|
# - error
|
||||||
- allowLoop: true
|
# - allowLoop: true
|
||||||
allowSwitch: true
|
# allowSwitch: true
|
||||||
no-lone-blocks: error
|
# no-lone-blocks: error
|
||||||
no-loop-func: error
|
# no-loop-func: error
|
||||||
no-magic-number: off
|
# no-magic-number: off
|
||||||
no-multi-spaces: off
|
# no-multi-spaces: off
|
||||||
no-multi-str: off
|
# no-multi-str: off
|
||||||
no-native-reassign: error
|
# no-native-reassign: error
|
||||||
no-new-func: error
|
# no-new-func: error
|
||||||
no-new-wrappers: error
|
# no-new-wrappers: error
|
||||||
no-new: error
|
# no-new: error
|
||||||
no-octal-escape: error
|
# no-octal-escape: error
|
||||||
no-octal: error
|
# no-octal: error
|
||||||
no-param-reassign: off
|
# no-param-reassign: off
|
||||||
no-proto: error
|
# no-proto: error
|
||||||
no-redeclare: error
|
# no-redeclare: error
|
||||||
no-restricted-properties: off
|
# no-restricted-properties: off
|
||||||
no-return-assign: error
|
# no-return-assign: error
|
||||||
no-return-await: off
|
# no-return-await: off
|
||||||
no-script-url: error
|
# no-script-url: error
|
||||||
no-self-assign: off
|
# no-self-assign: off
|
||||||
no-self-compare: error
|
# no-self-compare: error
|
||||||
no-sequences: off
|
# no-sequences: off
|
||||||
no-throw-literal: off
|
# no-throw-literal: off
|
||||||
no-unmodified-loop-condition: off
|
# no-unmodified-loop-condition: off
|
||||||
no-unused-expressions: error
|
# no-unused-expressions: error
|
||||||
no-unused-labels: off
|
# no-unused-labels: off
|
||||||
no-useless-call: error
|
# no-useless-call: error
|
||||||
no-useless-concat: error
|
# no-useless-concat: error
|
||||||
no-useless-escape: off
|
no-useless-escape: off
|
||||||
no-useless-return: off
|
# no-useless-return: off
|
||||||
no-void: error
|
# no-void: error
|
||||||
no-warning-comments: off
|
# no-warning-comments: off
|
||||||
no-with: error
|
# no-with: error
|
||||||
prefer-promise-reject-errors: off
|
# prefer-promise-reject-errors: off
|
||||||
radix: error
|
# radix: error
|
||||||
require-await: off
|
# require-await: off
|
||||||
vars-on-top: off
|
# vars-on-top: off
|
||||||
wrap-iife: error
|
# wrap-iife: error
|
||||||
yoda: off
|
# yoda: off
|
||||||
|
|
||||||
# Strict
|
# # Strict
|
||||||
strict: off
|
# strict: off
|
||||||
|
|
||||||
# Variables
|
# # Variables
|
||||||
init-declarations: off
|
# init-declarations: off
|
||||||
no-catch-shadow: error
|
# no-catch-shadow: error
|
||||||
no-delete-var: error
|
# no-delete-var: error
|
||||||
no-label-var: error
|
# no-label-var: error
|
||||||
no-restricted-globals: off
|
# no-restricted-globals: off
|
||||||
no-shadow-restricted-names: error
|
# no-shadow-restricted-names: error
|
||||||
no-shadow: off
|
# no-shadow: off
|
||||||
no-undef-init: error
|
# no-undef-init: error
|
||||||
no-undef: off
|
# no-undef: off
|
||||||
no-undefined: off
|
# no-undefined: off
|
||||||
no-unused-vars:
|
# no-unused-vars:
|
||||||
- warn
|
# - warn
|
||||||
-
|
# -
|
||||||
vars: local
|
# vars: local
|
||||||
no-use-before-define: off
|
# no-use-before-define: off
|
||||||
|
|
||||||
# Node.js and CommonJS
|
# # Node.js and CommonJS
|
||||||
callback-return: error
|
# callback-return: error
|
||||||
global-require: error
|
# global-require: error
|
||||||
handle-callback-err: error
|
# handle-callback-err: error
|
||||||
no-mixed-requires: off
|
# no-mixed-requires: off
|
||||||
no-new-require: off
|
# no-new-require: off
|
||||||
no-path-concat: error
|
# no-path-concat: error
|
||||||
no-process-env: off
|
# no-process-env: off
|
||||||
no-process-exit: error
|
# no-process-exit: error
|
||||||
no-restricted-modules: off
|
# no-restricted-modules: off
|
||||||
no-sync: off
|
# no-sync: off
|
||||||
|
|
||||||
# Stylistic Issues
|
# # Stylistic Issues
|
||||||
array-bracket-spacing: off
|
# array-bracket-spacing: off
|
||||||
block-spacing: off
|
# block-spacing: off
|
||||||
brace-style: off
|
# brace-style: off
|
||||||
camelcase: off
|
# camelcase: off
|
||||||
capitalized-comments: off
|
# capitalized-comments: off
|
||||||
comma-dangle:
|
# comma-dangle:
|
||||||
- error
|
# - error
|
||||||
- never
|
# - never
|
||||||
comma-spacing: off
|
# comma-spacing: off
|
||||||
comma-style: off
|
# comma-style: off
|
||||||
computed-property-spacing: off
|
# computed-property-spacing: off
|
||||||
consistent-this: off
|
# consistent-this: off
|
||||||
eol-last: off
|
# eol-last: off
|
||||||
func-call-spacing: off
|
# func-call-spacing: off
|
||||||
func-name-matching: off
|
# func-name-matching: off
|
||||||
func-names: off
|
# func-names: off
|
||||||
func-style: off
|
# func-style: off
|
||||||
id-length: off
|
# id-length: off
|
||||||
id-match: off
|
# id-match: off
|
||||||
indent: off
|
# indent: off
|
||||||
jsx-quotes: off
|
# jsx-quotes: off
|
||||||
key-spacing: off
|
# key-spacing: off
|
||||||
keyword-spacing: off
|
# keyword-spacing: off
|
||||||
line-comment-position: off
|
# line-comment-position: off
|
||||||
linebreak-style:
|
# linebreak-style:
|
||||||
- error
|
# - error
|
||||||
- unix
|
# - unix
|
||||||
lines-around-comment: off
|
# lines-around-comment: off
|
||||||
lines-around-directive: off
|
# lines-around-directive: off
|
||||||
max-depth: off
|
# max-depth: off
|
||||||
max-len: off
|
# max-len: off
|
||||||
max-nested-callbacks: off
|
# max-nested-callbacks: off
|
||||||
max-params: off
|
# max-params: off
|
||||||
max-statements-per-line: off
|
# max-statements-per-line: off
|
||||||
max-statements:
|
# max-statements:
|
||||||
- error
|
# - error
|
||||||
- 30
|
# - 30
|
||||||
multiline-ternary: off
|
# multiline-ternary: off
|
||||||
new-cap: off
|
# new-cap: off
|
||||||
new-parens: off
|
# new-parens: off
|
||||||
newline-after-var: off
|
# newline-after-var: off
|
||||||
newline-before-return: off
|
# newline-before-return: off
|
||||||
newline-per-chained-call: off
|
# newline-per-chained-call: off
|
||||||
no-array-constructor: off
|
# no-array-constructor: off
|
||||||
no-bitwise: off
|
# no-bitwise: off
|
||||||
no-continue: off
|
# no-continue: off
|
||||||
no-inline-comments: off
|
# no-inline-comments: off
|
||||||
no-lonely-if: off
|
# no-lonely-if: off
|
||||||
no-mixed-operators: off
|
# no-mixed-operators: off
|
||||||
no-mixed-spaces-and-tabs: off
|
# no-mixed-spaces-and-tabs: off
|
||||||
no-multi-assign: off
|
# no-multi-assign: off
|
||||||
no-multiple-empty-lines: off
|
# no-multiple-empty-lines: off
|
||||||
no-negated-condition: off
|
# no-negated-condition: off
|
||||||
no-nested-ternary: off
|
# no-nested-ternary: off
|
||||||
no-new-object: off
|
# no-new-object: off
|
||||||
no-plusplus: off
|
# no-plusplus: off
|
||||||
no-restricted-syntax: off
|
# no-restricted-syntax: off
|
||||||
no-spaced-func: off
|
# no-spaced-func: off
|
||||||
no-tabs: off
|
# no-tabs: off
|
||||||
no-ternary: off
|
# no-ternary: off
|
||||||
no-trailing-spaces: off
|
# no-trailing-spaces: off
|
||||||
no-underscore-dangle: off
|
# no-underscore-dangle: off
|
||||||
no-unneeded-ternary: off
|
# no-unneeded-ternary: off
|
||||||
object-curly-newline: off
|
# object-curly-newline: off
|
||||||
object-curly-spacing: off
|
# object-curly-spacing: off
|
||||||
object-property-newline: off
|
# object-property-newline: off
|
||||||
one-var-declaration-per-line: off
|
# one-var-declaration-per-line: off
|
||||||
one-var: off
|
# one-var: off
|
||||||
operator-assignment: off
|
# operator-assignment: off
|
||||||
operator-linebreak: off
|
# operator-linebreak: off
|
||||||
padded-blocks: off
|
# padded-blocks: off
|
||||||
quote-props: off
|
# quote-props: off
|
||||||
quotes:
|
# quotes:
|
||||||
- error
|
# - error
|
||||||
- single
|
# - single
|
||||||
require-jsdoc: off
|
# require-jsdoc: off
|
||||||
semi-spacing: off
|
# semi-spacing: off
|
||||||
semi:
|
# semi:
|
||||||
- error
|
# - error
|
||||||
- always
|
# - always
|
||||||
sort-keys: off
|
# sort-keys: off
|
||||||
sort-vars: off
|
# sort-vars: off
|
||||||
space-before-blocks: off
|
# space-before-blocks: off
|
||||||
space-before-function-paren: off
|
# space-before-function-paren: off
|
||||||
space-in-parens: off
|
# space-in-parens: off
|
||||||
space-infix-ops: off
|
# space-infix-ops: off
|
||||||
space-unary-ops: off
|
# space-unary-ops: off
|
||||||
spaced-comment: off
|
# spaced-comment: off
|
||||||
template-tag-spacing: off
|
# template-tag-spacing: off
|
||||||
unicode-bom: off
|
# unicode-bom: off
|
||||||
wrap-regex: off
|
# wrap-regex: off
|
||||||
|
|
||||||
# ECMAScript 6
|
# # ECMAScript 6
|
||||||
arrow-body-style: off
|
# arrow-body-style: off
|
||||||
arrow-parens: off
|
# arrow-parens: off
|
||||||
arrow-spacing: off
|
# arrow-spacing: off
|
||||||
constructor-super: off
|
# constructor-super: off
|
||||||
generator-star-spacing: off
|
# generator-star-spacing: off
|
||||||
no-class-assign: off
|
# no-class-assign: off
|
||||||
no-confusing-arrow: off
|
# no-confusing-arrow: off
|
||||||
no-const-assign: off
|
# no-const-assign: off
|
||||||
no-dupe-class-members: off
|
# no-dupe-class-members: off
|
||||||
no-duplicate-imports: off
|
# no-duplicate-imports: off
|
||||||
no-new-symbol: off
|
# no-new-symbol: off
|
||||||
no-restricted-imports: off
|
# no-restricted-imports: off
|
||||||
no-this-before-super: off
|
# no-this-before-super: off
|
||||||
no-useless-computed-key: off
|
# no-useless-computed-key: off
|
||||||
no-useless-constructor: off
|
# no-useless-constructor: off
|
||||||
no-useless-rename: off
|
# no-useless-rename: off
|
||||||
no-var: off
|
# no-var: off
|
||||||
object-shorthand: off
|
# object-shorthand: off
|
||||||
prefer-arrow-callback: off
|
# prefer-arrow-callback: off
|
||||||
prefer-const: off
|
# prefer-const: off
|
||||||
prefer-destructuring: off
|
# prefer-destructuring: off
|
||||||
prefer-numeric-literals: off
|
# prefer-numeric-literals: off
|
||||||
prefer-rest-params: off
|
# prefer-rest-params: off
|
||||||
prefer-reflect: off
|
# prefer-reflect: off
|
||||||
prefer-spread: off
|
# prefer-spread: off
|
||||||
prefer-template: off
|
# prefer-template: off
|
||||||
require-yield: off
|
# require-yield: off
|
||||||
rest-spread-spacing: off
|
# rest-spread-spacing: off
|
||||||
sort-imports: off
|
# sort-imports: off
|
||||||
symbol-description: off
|
# symbol-description: off
|
||||||
template-curly-spacing: off
|
# template-curly-spacing: off
|
||||||
yield-star-spacing: off
|
# yield-star-spacing: off
|
||||||
|
|
|
@ -8,7 +8,9 @@ about: Create a bug report
|
||||||
|
|
||||||
Thanks for reporting a bug for Portainer !
|
Thanks for reporting a bug for Portainer !
|
||||||
|
|
||||||
Do you need help or have a question? Come chat with us on Slack http://portainer.io/slack/ or gitter https://gitter.im/portainer/Lobby.
|
You can find more information about Portainer support framework policy here: https://www.portainer.io/2019/04/portainer-support-policy/
|
||||||
|
|
||||||
|
Do you need help or have a question? Come chat with us on Slack http://portainer.io/slack/.
|
||||||
|
|
||||||
Before opening a new issue, make sure that we do not have any duplicates
|
Before opening a new issue, make sure that we do not have any duplicates
|
||||||
already open. You can ensure this by searching the issue list for this
|
already open. You can ensure this by searching the issue list for this
|
||||||
|
|
|
@ -6,7 +6,9 @@ about: Ask us a question about Portainer usage or deployment
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
Do you need help or have a question? Come chat with us on Slack http://portainer.io/slack/ or gitter https://gitter.im/portainer/Lobby.
|
You can find more information about Portainer support framework policy here: https://www.portainer.io/2019/04/portainer-support-policy/
|
||||||
|
|
||||||
|
Do you need help or have a question? Come chat with us on Slack http://portainer.io/slack/
|
||||||
|
|
||||||
Also, be sure to check our FAQ and documentation first: https://portainer.readthedocs.io
|
Also, be sure to check our FAQ and documentation first: https://portainer.readthedocs.io
|
||||||
-->
|
-->
|
||||||
|
|
|
@ -8,7 +8,7 @@ about: Suggest a feature/enhancement that should be added in Portainer
|
||||||
|
|
||||||
Thanks for opening a feature request for Portainer !
|
Thanks for opening a feature request for Portainer !
|
||||||
|
|
||||||
Do you need help or have a question? Come chat with us on Slack http://portainer.io/slack/ or gitter https://gitter.im/portainer/Lobby.
|
Do you need help or have a question? Come chat with us on Slack http://portainer.io/slack/
|
||||||
|
|
||||||
Before opening a new issue, make sure that we do not have any duplicates
|
Before opening a new issue, make sure that we do not have any duplicates
|
||||||
already open. You can ensure this by searching the issue list for this
|
already open. You can ensure this by searching the issue list for this
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img title="portainer" src='https://github.com/portainer/portainer/blob/develop/assets/images/logo_alt.png?raw=true' />
|
<img title="portainer" src='https://github.com/portainer/portainer/blob/develop/assets/images/logo_alt.png?raw=true' />
|
||||||
</p>
|
</p>
|
||||||
|
@ -11,10 +10,8 @@
|
||||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YHXZJQNJQ36H6)
|
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YHXZJQNJQ36H6)
|
||||||
|
|
||||||
**_Portainer_** is a lightweight management UI which allows you to **easily** manage your different Docker environments (Docker hosts or Swarm clusters).
|
**_Portainer_** is a lightweight management UI which allows you to **easily** manage your different Docker environments (Docker hosts or Swarm clusters).
|
||||||
|
**_Portainer_** is meant to be as **simple** to deploy as it is to use. It consists of a single container that can run on any Docker engine (can be deployed as Linux container or a Windows native container, supports other platforms too).
|
||||||
**_Portainer_** is meant to be as **simple** to deploy as it is to use. It consists of a single container that can run on any Docker engine (can be deployed as Linux container or a Windows native container).
|
**_Portainer_** allows you to manage your all your Docker resources (containers, images, volumes, networks and more) ! It is compatible with the *standalone Docker* engine and with *Docker Swarm mode*.
|
||||||
|
|
||||||
**_Portainer_** allows you to manage your Docker containers, images, volumes, networks and more ! It is compatible with the *standalone Docker* engine and with *Docker Swarm mode*.
|
|
||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
|
|
||||||
|
@ -37,6 +34,8 @@ Unlike the public demo, the playground sessions are deleted after 4 hours. Apart
|
||||||
|
|
||||||
## Getting help
|
## Getting help
|
||||||
|
|
||||||
|
**NOTE**: You can find more information about Portainer support framework policy here: https://www.portainer.io/2019/04/portainer-support-policy/
|
||||||
|
|
||||||
* Issues: https://github.com/portainer/portainer/issues
|
* Issues: https://github.com/portainer/portainer/issues
|
||||||
* FAQ: https://portainer.readthedocs.io/en/latest/faq.html
|
* FAQ: https://portainer.readthedocs.io/en/latest/faq.html
|
||||||
* Slack (chat): https://portainer.io/slack/
|
* Slack (chat): https://portainer.io/slack/
|
||||||
|
|
|
@ -6,24 +6,25 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/dockerhub"
|
"github.com/portainer/portainer/api/bolt/dockerhub"
|
||||||
"github.com/portainer/portainer/bolt/endpoint"
|
"github.com/portainer/portainer/api/bolt/endpoint"
|
||||||
"github.com/portainer/portainer/bolt/endpointgroup"
|
"github.com/portainer/portainer/api/bolt/endpointgroup"
|
||||||
"github.com/portainer/portainer/bolt/extension"
|
"github.com/portainer/portainer/api/bolt/extension"
|
||||||
"github.com/portainer/portainer/bolt/migrator"
|
"github.com/portainer/portainer/api/bolt/migrator"
|
||||||
"github.com/portainer/portainer/bolt/registry"
|
"github.com/portainer/portainer/api/bolt/registry"
|
||||||
"github.com/portainer/portainer/bolt/resourcecontrol"
|
"github.com/portainer/portainer/api/bolt/resourcecontrol"
|
||||||
"github.com/portainer/portainer/bolt/schedule"
|
"github.com/portainer/portainer/api/bolt/role"
|
||||||
"github.com/portainer/portainer/bolt/settings"
|
"github.com/portainer/portainer/api/bolt/schedule"
|
||||||
"github.com/portainer/portainer/bolt/stack"
|
"github.com/portainer/portainer/api/bolt/settings"
|
||||||
"github.com/portainer/portainer/bolt/tag"
|
"github.com/portainer/portainer/api/bolt/stack"
|
||||||
"github.com/portainer/portainer/bolt/team"
|
"github.com/portainer/portainer/api/bolt/tag"
|
||||||
"github.com/portainer/portainer/bolt/teammembership"
|
"github.com/portainer/portainer/api/bolt/team"
|
||||||
"github.com/portainer/portainer/bolt/template"
|
"github.com/portainer/portainer/api/bolt/teammembership"
|
||||||
"github.com/portainer/portainer/bolt/user"
|
"github.com/portainer/portainer/api/bolt/template"
|
||||||
"github.com/portainer/portainer/bolt/version"
|
"github.com/portainer/portainer/api/bolt/user"
|
||||||
"github.com/portainer/portainer/bolt/webhook"
|
"github.com/portainer/portainer/api/bolt/version"
|
||||||
|
"github.com/portainer/portainer/api/bolt/webhook"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -37,6 +38,7 @@ type Store struct {
|
||||||
db *bolt.DB
|
db *bolt.DB
|
||||||
checkForDataMigration bool
|
checkForDataMigration bool
|
||||||
fileService portainer.FileService
|
fileService portainer.FileService
|
||||||
|
RoleService *role.Service
|
||||||
DockerHubService *dockerhub.Service
|
DockerHubService *dockerhub.Service
|
||||||
EndpointGroupService *endpointgroup.Service
|
EndpointGroupService *endpointgroup.Service
|
||||||
EndpointService *endpoint.Service
|
EndpointService *endpoint.Service
|
||||||
|
@ -89,29 +91,6 @@ func (store *Store) Open() error {
|
||||||
return store.initServices()
|
return store.initServices()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init creates the default data set.
|
|
||||||
func (store *Store) Init() error {
|
|
||||||
groups, err := store.EndpointGroupService.EndpointGroups()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(groups) == 0 {
|
|
||||||
unassignedGroup := &portainer.EndpointGroup{
|
|
||||||
Name: "Unassigned",
|
|
||||||
Description: "Unassigned endpoints",
|
|
||||||
Labels: []portainer.Pair{},
|
|
||||||
AuthorizedUsers: []portainer.UserID{},
|
|
||||||
AuthorizedTeams: []portainer.TeamID{},
|
|
||||||
Tags: []string{},
|
|
||||||
}
|
|
||||||
|
|
||||||
return store.EndpointGroupService.CreateEndpointGroup(unassignedGroup)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes the BoltDB database.
|
// Close closes the BoltDB database.
|
||||||
func (store *Store) Close() error {
|
func (store *Store) Close() error {
|
||||||
if store.db != nil {
|
if store.db != nil {
|
||||||
|
@ -140,6 +119,7 @@ func (store *Store) MigrateData() error {
|
||||||
EndpointGroupService: store.EndpointGroupService,
|
EndpointGroupService: store.EndpointGroupService,
|
||||||
EndpointService: store.EndpointService,
|
EndpointService: store.EndpointService,
|
||||||
ExtensionService: store.ExtensionService,
|
ExtensionService: store.ExtensionService,
|
||||||
|
RegistryService: store.RegistryService,
|
||||||
ResourceControlService: store.ResourceControlService,
|
ResourceControlService: store.ResourceControlService,
|
||||||
SettingsService: store.SettingsService,
|
SettingsService: store.SettingsService,
|
||||||
StackService: store.StackService,
|
StackService: store.StackService,
|
||||||
|
@ -162,6 +142,12 @@ func (store *Store) MigrateData() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *Store) initServices() error {
|
func (store *Store) initServices() error {
|
||||||
|
authorizationsetService, err := role.NewService(store.db)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
store.RoleService = authorizationsetService
|
||||||
|
|
||||||
dockerhubService, err := dockerhub.NewService(store.db)
|
dockerhubService, err := dockerhub.NewService(store.db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package dockerhub
|
package dockerhub
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package endpoint
|
package endpoint
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package endpointgroup
|
package endpointgroup
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package extension
|
package extension
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,432 @@
|
||||||
|
package bolt
|
||||||
|
|
||||||
|
import portainer "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
|
// Init creates the default data set.
|
||||||
|
func (store *Store) Init() error {
|
||||||
|
groups, err := store.EndpointGroupService.EndpointGroups()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(groups) == 0 {
|
||||||
|
unassignedGroup := &portainer.EndpointGroup{
|
||||||
|
Name: "Unassigned",
|
||||||
|
Description: "Unassigned endpoints",
|
||||||
|
Labels: []portainer.Pair{},
|
||||||
|
UserAccessPolicies: portainer.UserAccessPolicies{},
|
||||||
|
TeamAccessPolicies: portainer.TeamAccessPolicies{},
|
||||||
|
Tags: []string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.EndpointGroupService.CreateEndpointGroup(unassignedGroup)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
roles, err := store.RoleService.Roles()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(roles) == 0 {
|
||||||
|
environmentAdministratorRole := &portainer.Role{
|
||||||
|
Name: "Endpoint administrator",
|
||||||
|
Description: "Full control of all resources in an endpoint",
|
||||||
|
Authorizations: map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationDockerContainerArchiveInfo: true,
|
||||||
|
portainer.OperationDockerContainerList: true,
|
||||||
|
portainer.OperationDockerContainerExport: true,
|
||||||
|
portainer.OperationDockerContainerChanges: true,
|
||||||
|
portainer.OperationDockerContainerInspect: true,
|
||||||
|
portainer.OperationDockerContainerTop: true,
|
||||||
|
portainer.OperationDockerContainerLogs: true,
|
||||||
|
portainer.OperationDockerContainerStats: true,
|
||||||
|
portainer.OperationDockerContainerAttachWebsocket: true,
|
||||||
|
portainer.OperationDockerContainerArchive: true,
|
||||||
|
portainer.OperationDockerContainerCreate: true,
|
||||||
|
portainer.OperationDockerContainerPrune: true,
|
||||||
|
portainer.OperationDockerContainerKill: true,
|
||||||
|
portainer.OperationDockerContainerPause: true,
|
||||||
|
portainer.OperationDockerContainerUnpause: true,
|
||||||
|
portainer.OperationDockerContainerRestart: true,
|
||||||
|
portainer.OperationDockerContainerStart: true,
|
||||||
|
portainer.OperationDockerContainerStop: true,
|
||||||
|
portainer.OperationDockerContainerWait: true,
|
||||||
|
portainer.OperationDockerContainerResize: true,
|
||||||
|
portainer.OperationDockerContainerAttach: true,
|
||||||
|
portainer.OperationDockerContainerExec: true,
|
||||||
|
portainer.OperationDockerContainerRename: true,
|
||||||
|
portainer.OperationDockerContainerUpdate: true,
|
||||||
|
portainer.OperationDockerContainerPutContainerArchive: true,
|
||||||
|
portainer.OperationDockerContainerDelete: true,
|
||||||
|
portainer.OperationDockerImageList: true,
|
||||||
|
portainer.OperationDockerImageSearch: true,
|
||||||
|
portainer.OperationDockerImageGetAll: true,
|
||||||
|
portainer.OperationDockerImageGet: true,
|
||||||
|
portainer.OperationDockerImageHistory: true,
|
||||||
|
portainer.OperationDockerImageInspect: true,
|
||||||
|
portainer.OperationDockerImageLoad: true,
|
||||||
|
portainer.OperationDockerImageCreate: true,
|
||||||
|
portainer.OperationDockerImagePrune: true,
|
||||||
|
portainer.OperationDockerImagePush: true,
|
||||||
|
portainer.OperationDockerImageTag: true,
|
||||||
|
portainer.OperationDockerImageDelete: true,
|
||||||
|
portainer.OperationDockerImageCommit: true,
|
||||||
|
portainer.OperationDockerImageBuild: true,
|
||||||
|
portainer.OperationDockerNetworkList: true,
|
||||||
|
portainer.OperationDockerNetworkInspect: true,
|
||||||
|
portainer.OperationDockerNetworkCreate: true,
|
||||||
|
portainer.OperationDockerNetworkConnect: true,
|
||||||
|
portainer.OperationDockerNetworkDisconnect: true,
|
||||||
|
portainer.OperationDockerNetworkPrune: true,
|
||||||
|
portainer.OperationDockerNetworkDelete: true,
|
||||||
|
portainer.OperationDockerVolumeList: true,
|
||||||
|
portainer.OperationDockerVolumeInspect: true,
|
||||||
|
portainer.OperationDockerVolumeCreate: true,
|
||||||
|
portainer.OperationDockerVolumePrune: true,
|
||||||
|
portainer.OperationDockerVolumeDelete: true,
|
||||||
|
portainer.OperationDockerExecInspect: true,
|
||||||
|
portainer.OperationDockerExecStart: true,
|
||||||
|
portainer.OperationDockerExecResize: true,
|
||||||
|
portainer.OperationDockerSwarmInspect: true,
|
||||||
|
portainer.OperationDockerSwarmUnlockKey: true,
|
||||||
|
portainer.OperationDockerSwarmInit: true,
|
||||||
|
portainer.OperationDockerSwarmJoin: true,
|
||||||
|
portainer.OperationDockerSwarmLeave: true,
|
||||||
|
portainer.OperationDockerSwarmUpdate: true,
|
||||||
|
portainer.OperationDockerSwarmUnlock: true,
|
||||||
|
portainer.OperationDockerNodeList: true,
|
||||||
|
portainer.OperationDockerNodeInspect: true,
|
||||||
|
portainer.OperationDockerNodeUpdate: true,
|
||||||
|
portainer.OperationDockerNodeDelete: true,
|
||||||
|
portainer.OperationDockerServiceList: true,
|
||||||
|
portainer.OperationDockerServiceInspect: true,
|
||||||
|
portainer.OperationDockerServiceLogs: true,
|
||||||
|
portainer.OperationDockerServiceCreate: true,
|
||||||
|
portainer.OperationDockerServiceUpdate: true,
|
||||||
|
portainer.OperationDockerServiceDelete: true,
|
||||||
|
portainer.OperationDockerSecretList: true,
|
||||||
|
portainer.OperationDockerSecretInspect: true,
|
||||||
|
portainer.OperationDockerSecretCreate: true,
|
||||||
|
portainer.OperationDockerSecretUpdate: true,
|
||||||
|
portainer.OperationDockerSecretDelete: true,
|
||||||
|
portainer.OperationDockerConfigList: true,
|
||||||
|
portainer.OperationDockerConfigInspect: true,
|
||||||
|
portainer.OperationDockerConfigCreate: true,
|
||||||
|
portainer.OperationDockerConfigUpdate: true,
|
||||||
|
portainer.OperationDockerConfigDelete: true,
|
||||||
|
portainer.OperationDockerTaskList: true,
|
||||||
|
portainer.OperationDockerTaskInspect: true,
|
||||||
|
portainer.OperationDockerTaskLogs: true,
|
||||||
|
portainer.OperationDockerPluginList: true,
|
||||||
|
portainer.OperationDockerPluginPrivileges: true,
|
||||||
|
portainer.OperationDockerPluginInspect: true,
|
||||||
|
portainer.OperationDockerPluginPull: true,
|
||||||
|
portainer.OperationDockerPluginCreate: true,
|
||||||
|
portainer.OperationDockerPluginEnable: true,
|
||||||
|
portainer.OperationDockerPluginDisable: true,
|
||||||
|
portainer.OperationDockerPluginPush: true,
|
||||||
|
portainer.OperationDockerPluginUpgrade: true,
|
||||||
|
portainer.OperationDockerPluginSet: true,
|
||||||
|
portainer.OperationDockerPluginDelete: true,
|
||||||
|
portainer.OperationDockerSessionStart: true,
|
||||||
|
portainer.OperationDockerDistributionInspect: true,
|
||||||
|
portainer.OperationDockerBuildPrune: true,
|
||||||
|
portainer.OperationDockerBuildCancel: true,
|
||||||
|
portainer.OperationDockerPing: true,
|
||||||
|
portainer.OperationDockerInfo: true,
|
||||||
|
portainer.OperationDockerVersion: true,
|
||||||
|
portainer.OperationDockerEvents: true,
|
||||||
|
portainer.OperationDockerSystem: true,
|
||||||
|
portainer.OperationDockerUndefined: true,
|
||||||
|
portainer.OperationDockerAgentPing: true,
|
||||||
|
portainer.OperationDockerAgentList: true,
|
||||||
|
portainer.OperationDockerAgentHostInfo: true,
|
||||||
|
portainer.OperationDockerAgentBrowseDelete: true,
|
||||||
|
portainer.OperationDockerAgentBrowseGet: true,
|
||||||
|
portainer.OperationDockerAgentBrowseList: true,
|
||||||
|
portainer.OperationDockerAgentBrowsePut: true,
|
||||||
|
portainer.OperationDockerAgentBrowseRename: true,
|
||||||
|
portainer.OperationDockerAgentUndefined: true,
|
||||||
|
portainer.OperationPortainerResourceControlCreate: true,
|
||||||
|
portainer.OperationPortainerResourceControlUpdate: true,
|
||||||
|
portainer.OperationPortainerResourceControlDelete: true,
|
||||||
|
portainer.OperationPortainerStackList: true,
|
||||||
|
portainer.OperationPortainerStackInspect: true,
|
||||||
|
portainer.OperationPortainerStackFile: true,
|
||||||
|
portainer.OperationPortainerStackCreate: true,
|
||||||
|
portainer.OperationPortainerStackMigrate: true,
|
||||||
|
portainer.OperationPortainerStackUpdate: true,
|
||||||
|
portainer.OperationPortainerStackDelete: true,
|
||||||
|
portainer.OperationPortainerWebsocketExec: true,
|
||||||
|
portainer.OperationPortainerWebhookList: true,
|
||||||
|
portainer.OperationPortainerWebhookCreate: true,
|
||||||
|
portainer.OperationPortainerWebhookDelete: true,
|
||||||
|
portainer.OperationIntegrationStoridgeAdmin: true,
|
||||||
|
portainer.EndpointResourcesAccess: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.RoleService.CreateRole(environmentAdministratorRole)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
environmentReadOnlyUserRole := &portainer.Role{
|
||||||
|
Name: "Helpdesk",
|
||||||
|
Description: "Read-only access of all resources in an endpoint",
|
||||||
|
Authorizations: map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationDockerContainerArchiveInfo: true,
|
||||||
|
portainer.OperationDockerContainerList: true,
|
||||||
|
portainer.OperationDockerContainerChanges: true,
|
||||||
|
portainer.OperationDockerContainerInspect: true,
|
||||||
|
portainer.OperationDockerContainerTop: true,
|
||||||
|
portainer.OperationDockerContainerLogs: true,
|
||||||
|
portainer.OperationDockerContainerStats: true,
|
||||||
|
portainer.OperationDockerImageList: true,
|
||||||
|
portainer.OperationDockerImageSearch: true,
|
||||||
|
portainer.OperationDockerImageGetAll: true,
|
||||||
|
portainer.OperationDockerImageGet: true,
|
||||||
|
portainer.OperationDockerImageHistory: true,
|
||||||
|
portainer.OperationDockerImageInspect: true,
|
||||||
|
portainer.OperationDockerNetworkList: true,
|
||||||
|
portainer.OperationDockerNetworkInspect: true,
|
||||||
|
portainer.OperationDockerVolumeList: true,
|
||||||
|
portainer.OperationDockerVolumeInspect: true,
|
||||||
|
portainer.OperationDockerSwarmInspect: true,
|
||||||
|
portainer.OperationDockerNodeList: true,
|
||||||
|
portainer.OperationDockerNodeInspect: true,
|
||||||
|
portainer.OperationDockerServiceList: true,
|
||||||
|
portainer.OperationDockerServiceInspect: true,
|
||||||
|
portainer.OperationDockerServiceLogs: true,
|
||||||
|
portainer.OperationDockerSecretList: true,
|
||||||
|
portainer.OperationDockerSecretInspect: true,
|
||||||
|
portainer.OperationDockerConfigList: true,
|
||||||
|
portainer.OperationDockerConfigInspect: true,
|
||||||
|
portainer.OperationDockerTaskList: true,
|
||||||
|
portainer.OperationDockerTaskInspect: true,
|
||||||
|
portainer.OperationDockerTaskLogs: true,
|
||||||
|
portainer.OperationDockerPluginList: true,
|
||||||
|
portainer.OperationDockerDistributionInspect: true,
|
||||||
|
portainer.OperationDockerPing: true,
|
||||||
|
portainer.OperationDockerInfo: true,
|
||||||
|
portainer.OperationDockerVersion: true,
|
||||||
|
portainer.OperationDockerEvents: true,
|
||||||
|
portainer.OperationDockerSystem: true,
|
||||||
|
portainer.OperationDockerAgentPing: true,
|
||||||
|
portainer.OperationDockerAgentList: true,
|
||||||
|
portainer.OperationDockerAgentHostInfo: true,
|
||||||
|
portainer.OperationDockerAgentBrowseGet: true,
|
||||||
|
portainer.OperationDockerAgentBrowseList: true,
|
||||||
|
portainer.OperationPortainerStackList: true,
|
||||||
|
portainer.OperationPortainerStackInspect: true,
|
||||||
|
portainer.OperationPortainerStackFile: true,
|
||||||
|
portainer.OperationPortainerWebhookList: true,
|
||||||
|
portainer.EndpointResourcesAccess: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.RoleService.CreateRole(environmentReadOnlyUserRole)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
standardUserRole := &portainer.Role{
|
||||||
|
Name: "Standard user",
|
||||||
|
Description: "Full control of assigned resources in an endpoint",
|
||||||
|
Authorizations: map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationDockerContainerArchiveInfo: true,
|
||||||
|
portainer.OperationDockerContainerList: true,
|
||||||
|
portainer.OperationDockerContainerExport: true,
|
||||||
|
portainer.OperationDockerContainerChanges: true,
|
||||||
|
portainer.OperationDockerContainerInspect: true,
|
||||||
|
portainer.OperationDockerContainerTop: true,
|
||||||
|
portainer.OperationDockerContainerLogs: true,
|
||||||
|
portainer.OperationDockerContainerStats: true,
|
||||||
|
portainer.OperationDockerContainerAttachWebsocket: true,
|
||||||
|
portainer.OperationDockerContainerArchive: true,
|
||||||
|
portainer.OperationDockerContainerCreate: true,
|
||||||
|
portainer.OperationDockerContainerKill: true,
|
||||||
|
portainer.OperationDockerContainerPause: true,
|
||||||
|
portainer.OperationDockerContainerUnpause: true,
|
||||||
|
portainer.OperationDockerContainerRestart: true,
|
||||||
|
portainer.OperationDockerContainerStart: true,
|
||||||
|
portainer.OperationDockerContainerStop: true,
|
||||||
|
portainer.OperationDockerContainerWait: true,
|
||||||
|
portainer.OperationDockerContainerResize: true,
|
||||||
|
portainer.OperationDockerContainerAttach: true,
|
||||||
|
portainer.OperationDockerContainerExec: true,
|
||||||
|
portainer.OperationDockerContainerRename: true,
|
||||||
|
portainer.OperationDockerContainerUpdate: true,
|
||||||
|
portainer.OperationDockerContainerPutContainerArchive: true,
|
||||||
|
portainer.OperationDockerContainerDelete: true,
|
||||||
|
portainer.OperationDockerImageList: true,
|
||||||
|
portainer.OperationDockerImageSearch: true,
|
||||||
|
portainer.OperationDockerImageGetAll: true,
|
||||||
|
portainer.OperationDockerImageGet: true,
|
||||||
|
portainer.OperationDockerImageHistory: true,
|
||||||
|
portainer.OperationDockerImageInspect: true,
|
||||||
|
portainer.OperationDockerImageLoad: true,
|
||||||
|
portainer.OperationDockerImageCreate: true,
|
||||||
|
portainer.OperationDockerImagePush: true,
|
||||||
|
portainer.OperationDockerImageTag: true,
|
||||||
|
portainer.OperationDockerImageDelete: true,
|
||||||
|
portainer.OperationDockerImageCommit: true,
|
||||||
|
portainer.OperationDockerImageBuild: true,
|
||||||
|
portainer.OperationDockerNetworkList: true,
|
||||||
|
portainer.OperationDockerNetworkInspect: true,
|
||||||
|
portainer.OperationDockerNetworkCreate: true,
|
||||||
|
portainer.OperationDockerNetworkConnect: true,
|
||||||
|
portainer.OperationDockerNetworkDisconnect: true,
|
||||||
|
portainer.OperationDockerNetworkDelete: true,
|
||||||
|
portainer.OperationDockerVolumeList: true,
|
||||||
|
portainer.OperationDockerVolumeInspect: true,
|
||||||
|
portainer.OperationDockerVolumeCreate: true,
|
||||||
|
portainer.OperationDockerVolumeDelete: true,
|
||||||
|
portainer.OperationDockerExecInspect: true,
|
||||||
|
portainer.OperationDockerExecStart: true,
|
||||||
|
portainer.OperationDockerExecResize: true,
|
||||||
|
portainer.OperationDockerSwarmInspect: true,
|
||||||
|
portainer.OperationDockerSwarmUnlockKey: true,
|
||||||
|
portainer.OperationDockerSwarmInit: true,
|
||||||
|
portainer.OperationDockerSwarmJoin: true,
|
||||||
|
portainer.OperationDockerSwarmLeave: true,
|
||||||
|
portainer.OperationDockerSwarmUpdate: true,
|
||||||
|
portainer.OperationDockerSwarmUnlock: true,
|
||||||
|
portainer.OperationDockerNodeList: true,
|
||||||
|
portainer.OperationDockerNodeInspect: true,
|
||||||
|
portainer.OperationDockerNodeUpdate: true,
|
||||||
|
portainer.OperationDockerNodeDelete: true,
|
||||||
|
portainer.OperationDockerServiceList: true,
|
||||||
|
portainer.OperationDockerServiceInspect: true,
|
||||||
|
portainer.OperationDockerServiceLogs: true,
|
||||||
|
portainer.OperationDockerServiceCreate: true,
|
||||||
|
portainer.OperationDockerServiceUpdate: true,
|
||||||
|
portainer.OperationDockerServiceDelete: true,
|
||||||
|
portainer.OperationDockerSecretList: true,
|
||||||
|
portainer.OperationDockerSecretInspect: true,
|
||||||
|
portainer.OperationDockerSecretCreate: true,
|
||||||
|
portainer.OperationDockerSecretUpdate: true,
|
||||||
|
portainer.OperationDockerSecretDelete: true,
|
||||||
|
portainer.OperationDockerConfigList: true,
|
||||||
|
portainer.OperationDockerConfigInspect: true,
|
||||||
|
portainer.OperationDockerConfigCreate: true,
|
||||||
|
portainer.OperationDockerConfigUpdate: true,
|
||||||
|
portainer.OperationDockerConfigDelete: true,
|
||||||
|
portainer.OperationDockerTaskList: true,
|
||||||
|
portainer.OperationDockerTaskInspect: true,
|
||||||
|
portainer.OperationDockerTaskLogs: true,
|
||||||
|
portainer.OperationDockerPluginList: true,
|
||||||
|
portainer.OperationDockerPluginPrivileges: true,
|
||||||
|
portainer.OperationDockerPluginInspect: true,
|
||||||
|
portainer.OperationDockerPluginPull: true,
|
||||||
|
portainer.OperationDockerPluginCreate: true,
|
||||||
|
portainer.OperationDockerPluginEnable: true,
|
||||||
|
portainer.OperationDockerPluginDisable: true,
|
||||||
|
portainer.OperationDockerPluginPush: true,
|
||||||
|
portainer.OperationDockerPluginUpgrade: true,
|
||||||
|
portainer.OperationDockerPluginSet: true,
|
||||||
|
portainer.OperationDockerPluginDelete: true,
|
||||||
|
portainer.OperationDockerSessionStart: true,
|
||||||
|
portainer.OperationDockerDistributionInspect: true,
|
||||||
|
portainer.OperationDockerBuildPrune: true,
|
||||||
|
portainer.OperationDockerBuildCancel: true,
|
||||||
|
portainer.OperationDockerPing: true,
|
||||||
|
portainer.OperationDockerInfo: true,
|
||||||
|
portainer.OperationDockerVersion: true,
|
||||||
|
portainer.OperationDockerEvents: true,
|
||||||
|
portainer.OperationDockerSystem: true,
|
||||||
|
portainer.OperationDockerUndefined: true,
|
||||||
|
portainer.OperationDockerAgentPing: true,
|
||||||
|
portainer.OperationDockerAgentList: true,
|
||||||
|
portainer.OperationDockerAgentHostInfo: true,
|
||||||
|
portainer.OperationDockerAgentBrowseDelete: true,
|
||||||
|
portainer.OperationDockerAgentBrowseGet: true,
|
||||||
|
portainer.OperationDockerAgentBrowseList: true,
|
||||||
|
portainer.OperationDockerAgentBrowsePut: true,
|
||||||
|
portainer.OperationDockerAgentBrowseRename: true,
|
||||||
|
portainer.OperationDockerAgentUndefined: true,
|
||||||
|
portainer.OperationPortainerResourceControlCreate: true,
|
||||||
|
portainer.OperationPortainerResourceControlUpdate: true,
|
||||||
|
portainer.OperationPortainerResourceControlDelete: true,
|
||||||
|
portainer.OperationPortainerStackList: true,
|
||||||
|
portainer.OperationPortainerStackInspect: true,
|
||||||
|
portainer.OperationPortainerStackFile: true,
|
||||||
|
portainer.OperationPortainerStackCreate: true,
|
||||||
|
portainer.OperationPortainerStackMigrate: true,
|
||||||
|
portainer.OperationPortainerStackUpdate: true,
|
||||||
|
portainer.OperationPortainerStackDelete: true,
|
||||||
|
portainer.OperationPortainerWebsocketExec: true,
|
||||||
|
portainer.OperationPortainerWebhookList: true,
|
||||||
|
portainer.OperationPortainerWebhookCreate: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.RoleService.CreateRole(standardUserRole)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
readOnlyUserRole := &portainer.Role{
|
||||||
|
Name: "Read-only user",
|
||||||
|
Description: "Read-only access of assigned resources in an endpoint",
|
||||||
|
Authorizations: map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationDockerContainerArchiveInfo: true,
|
||||||
|
portainer.OperationDockerContainerList: true,
|
||||||
|
portainer.OperationDockerContainerChanges: true,
|
||||||
|
portainer.OperationDockerContainerInspect: true,
|
||||||
|
portainer.OperationDockerContainerTop: true,
|
||||||
|
portainer.OperationDockerContainerLogs: true,
|
||||||
|
portainer.OperationDockerContainerStats: true,
|
||||||
|
portainer.OperationDockerImageList: true,
|
||||||
|
portainer.OperationDockerImageSearch: true,
|
||||||
|
portainer.OperationDockerImageGetAll: true,
|
||||||
|
portainer.OperationDockerImageGet: true,
|
||||||
|
portainer.OperationDockerImageHistory: true,
|
||||||
|
portainer.OperationDockerImageInspect: true,
|
||||||
|
portainer.OperationDockerNetworkList: true,
|
||||||
|
portainer.OperationDockerNetworkInspect: true,
|
||||||
|
portainer.OperationDockerVolumeList: true,
|
||||||
|
portainer.OperationDockerVolumeInspect: true,
|
||||||
|
portainer.OperationDockerSwarmInspect: true,
|
||||||
|
portainer.OperationDockerNodeList: true,
|
||||||
|
portainer.OperationDockerNodeInspect: true,
|
||||||
|
portainer.OperationDockerServiceList: true,
|
||||||
|
portainer.OperationDockerServiceInspect: true,
|
||||||
|
portainer.OperationDockerServiceLogs: true,
|
||||||
|
portainer.OperationDockerSecretList: true,
|
||||||
|
portainer.OperationDockerSecretInspect: true,
|
||||||
|
portainer.OperationDockerConfigList: true,
|
||||||
|
portainer.OperationDockerConfigInspect: true,
|
||||||
|
portainer.OperationDockerTaskList: true,
|
||||||
|
portainer.OperationDockerTaskInspect: true,
|
||||||
|
portainer.OperationDockerTaskLogs: true,
|
||||||
|
portainer.OperationDockerPluginList: true,
|
||||||
|
portainer.OperationDockerDistributionInspect: true,
|
||||||
|
portainer.OperationDockerPing: true,
|
||||||
|
portainer.OperationDockerInfo: true,
|
||||||
|
portainer.OperationDockerVersion: true,
|
||||||
|
portainer.OperationDockerEvents: true,
|
||||||
|
portainer.OperationDockerSystem: true,
|
||||||
|
portainer.OperationDockerAgentPing: true,
|
||||||
|
portainer.OperationDockerAgentList: true,
|
||||||
|
portainer.OperationDockerAgentHostInfo: true,
|
||||||
|
portainer.OperationDockerAgentBrowseGet: true,
|
||||||
|
portainer.OperationDockerAgentBrowseList: true,
|
||||||
|
portainer.OperationPortainerStackList: true,
|
||||||
|
portainer.OperationPortainerStackInspect: true,
|
||||||
|
portainer.OperationPortainerStackFile: true,
|
||||||
|
portainer.OperationPortainerWebhookList: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.RoleService.CreateRole(readOnlyUserRole)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Itob returns an 8-byte big endian representation of v.
|
// Itob returns an 8-byte big endian representation of v.
|
||||||
|
|
|
@ -2,8 +2,8 @@ package migrator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/user"
|
"github.com/portainer/portainer/api/bolt/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *Migrator) updateAdminUserToDBVersion1() error {
|
func (m *Migrator) updateAdminUserToDBVersion1() error {
|
||||||
|
|
|
@ -2,8 +2,8 @@ package migrator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *Migrator) updateResourceControlsToDBVersion2() error {
|
func (m *Migrator) updateResourceControlsToDBVersion2() error {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package migrator
|
package migrator
|
||||||
|
|
||||||
import "github.com/portainer/portainer"
|
import "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
func (m *Migrator) updateEndpointsToVersion11() error {
|
func (m *Migrator) updateEndpointsToVersion11() error {
|
||||||
legacyEndpoints, err := m.endpointService.Endpoints()
|
legacyEndpoints, err := m.endpointService.Endpoints()
|
||||||
|
|
|
@ -5,9 +5,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
"github.com/portainer/portainer/bolt/stack"
|
"github.com/portainer/portainer/api/bolt/stack"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *Migrator) updateEndpointsToVersion12() error {
|
func (m *Migrator) updateEndpointsToVersion12() error {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package migrator
|
package migrator
|
||||||
|
|
||||||
import "github.com/portainer/portainer"
|
import "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
func (m *Migrator) updateSettingsToVersion13() error {
|
func (m *Migrator) updateSettingsToVersion13() error {
|
||||||
legacySettings, err := m.settingsService.Settings()
|
legacySettings, err := m.settingsService.Settings()
|
||||||
|
|
|
@ -3,7 +3,7 @@ package migrator
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *Migrator) updateSettingsToDBVersion15() error {
|
func (m *Migrator) updateSettingsToDBVersion15() error {
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
package migrator
|
||||||
|
|
||||||
|
import (
|
||||||
|
portainer "github.com/portainer/portainer/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *Migrator) updateUsersToDBVersion18() error {
|
||||||
|
legacyUsers, err := m.userService.Users()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, user := range legacyUsers {
|
||||||
|
user.PortainerAuthorizations = map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationPortainerDockerHubInspect: true,
|
||||||
|
portainer.OperationPortainerEndpointGroupList: true,
|
||||||
|
portainer.OperationPortainerEndpointList: true,
|
||||||
|
portainer.OperationPortainerEndpointInspect: true,
|
||||||
|
portainer.OperationPortainerEndpointExtensionAdd: true,
|
||||||
|
portainer.OperationPortainerEndpointExtensionRemove: true,
|
||||||
|
portainer.OperationPortainerExtensionList: true,
|
||||||
|
portainer.OperationPortainerMOTD: true,
|
||||||
|
portainer.OperationPortainerRegistryList: true,
|
||||||
|
portainer.OperationPortainerRegistryInspect: true,
|
||||||
|
portainer.OperationPortainerTeamList: true,
|
||||||
|
portainer.OperationPortainerTemplateList: true,
|
||||||
|
portainer.OperationPortainerTemplateInspect: true,
|
||||||
|
portainer.OperationPortainerUserList: true,
|
||||||
|
portainer.OperationPortainerUserMemberships: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.userService.UpdateUser(user.ID, &user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Migrator) updateEndpointsToDBVersion18() error {
|
||||||
|
legacyEndpoints, err := m.endpointService.Endpoints()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpoint := range legacyEndpoints {
|
||||||
|
endpoint.UserAccessPolicies = make(portainer.UserAccessPolicies)
|
||||||
|
for _, userID := range endpoint.AuthorizedUsers {
|
||||||
|
endpoint.UserAccessPolicies[userID] = portainer.AccessPolicy{
|
||||||
|
RoleID: 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint.TeamAccessPolicies = make(portainer.TeamAccessPolicies)
|
||||||
|
for _, teamID := range endpoint.AuthorizedTeams {
|
||||||
|
endpoint.TeamAccessPolicies[teamID] = portainer.AccessPolicy{
|
||||||
|
RoleID: 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.endpointService.UpdateEndpoint(endpoint.ID, &endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Migrator) updateEndpointGroupsToDBVersion18() error {
|
||||||
|
legacyEndpointGroups, err := m.endpointGroupService.EndpointGroups()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpointGroup := range legacyEndpointGroups {
|
||||||
|
endpointGroup.UserAccessPolicies = make(portainer.UserAccessPolicies)
|
||||||
|
for _, userID := range endpointGroup.AuthorizedUsers {
|
||||||
|
endpointGroup.UserAccessPolicies[userID] = portainer.AccessPolicy{
|
||||||
|
RoleID: 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointGroup.TeamAccessPolicies = make(portainer.TeamAccessPolicies)
|
||||||
|
for _, teamID := range endpointGroup.AuthorizedTeams {
|
||||||
|
endpointGroup.TeamAccessPolicies[teamID] = portainer.AccessPolicy{
|
||||||
|
RoleID: 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.endpointGroupService.UpdateEndpointGroup(endpointGroup.ID, &endpointGroup)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Migrator) updateRegistriesToDBVersion18() error {
|
||||||
|
legacyRegistries, err := m.registryService.Registries()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, registry := range legacyRegistries {
|
||||||
|
registry.UserAccessPolicies = make(portainer.UserAccessPolicies)
|
||||||
|
for _, userID := range registry.AuthorizedUsers {
|
||||||
|
registry.UserAccessPolicies[userID] = portainer.AccessPolicy{}
|
||||||
|
}
|
||||||
|
|
||||||
|
registry.TeamAccessPolicies = make(portainer.TeamAccessPolicies)
|
||||||
|
for _, teamID := range registry.AuthorizedTeams {
|
||||||
|
registry.TeamAccessPolicies[teamID] = portainer.AccessPolicy{}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.registryService.UpdateRegistry(registry.ID, ®istry)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package migrator
|
package migrator
|
||||||
|
|
||||||
import "github.com/portainer/portainer"
|
import "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
func (m *Migrator) updateSettingsToDBVersion3() error {
|
func (m *Migrator) updateSettingsToDBVersion3() error {
|
||||||
legacySettings, err := m.settingsService.Settings()
|
legacySettings, err := m.settingsService.Settings()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package migrator
|
package migrator
|
||||||
|
|
||||||
import "github.com/portainer/portainer"
|
import "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
func (m *Migrator) updateEndpointsToDBVersion4() error {
|
func (m *Migrator) updateEndpointsToDBVersion4() error {
|
||||||
legacyEndpoints, err := m.endpointService.Endpoints()
|
legacyEndpoints, err := m.endpointService.Endpoints()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package migrator
|
package migrator
|
||||||
|
|
||||||
import "github.com/portainer/portainer"
|
import "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
func (m *Migrator) updateEndpointsToVersion8() error {
|
func (m *Migrator) updateEndpointsToVersion8() error {
|
||||||
legacyEndpoints, err := m.endpointService.Endpoints()
|
legacyEndpoints, err := m.endpointService.Endpoints()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package migrator
|
package migrator
|
||||||
|
|
||||||
import "github.com/portainer/portainer"
|
import "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
func (m *Migrator) updateEndpointsToVersion9() error {
|
func (m *Migrator) updateEndpointsToVersion9() error {
|
||||||
legacyEndpoints, err := m.endpointService.Endpoints()
|
legacyEndpoints, err := m.endpointService.Endpoints()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package migrator
|
package migrator
|
||||||
|
|
||||||
import "github.com/portainer/portainer"
|
import "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
func (m *Migrator) updateEndpointsToVersion10() error {
|
func (m *Migrator) updateEndpointsToVersion10() error {
|
||||||
legacyEndpoints, err := m.endpointService.Endpoints()
|
legacyEndpoints, err := m.endpointService.Endpoints()
|
||||||
|
|
|
@ -2,16 +2,17 @@ package migrator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/endpoint"
|
"github.com/portainer/portainer/api/bolt/endpoint"
|
||||||
"github.com/portainer/portainer/bolt/endpointgroup"
|
"github.com/portainer/portainer/api/bolt/endpointgroup"
|
||||||
"github.com/portainer/portainer/bolt/extension"
|
"github.com/portainer/portainer/api/bolt/extension"
|
||||||
"github.com/portainer/portainer/bolt/resourcecontrol"
|
"github.com/portainer/portainer/api/bolt/registry"
|
||||||
"github.com/portainer/portainer/bolt/settings"
|
"github.com/portainer/portainer/api/bolt/resourcecontrol"
|
||||||
"github.com/portainer/portainer/bolt/stack"
|
"github.com/portainer/portainer/api/bolt/settings"
|
||||||
"github.com/portainer/portainer/bolt/template"
|
"github.com/portainer/portainer/api/bolt/stack"
|
||||||
"github.com/portainer/portainer/bolt/user"
|
"github.com/portainer/portainer/api/bolt/template"
|
||||||
"github.com/portainer/portainer/bolt/version"
|
"github.com/portainer/portainer/api/bolt/user"
|
||||||
|
"github.com/portainer/portainer/api/bolt/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -22,6 +23,7 @@ type (
|
||||||
endpointGroupService *endpointgroup.Service
|
endpointGroupService *endpointgroup.Service
|
||||||
endpointService *endpoint.Service
|
endpointService *endpoint.Service
|
||||||
extensionService *extension.Service
|
extensionService *extension.Service
|
||||||
|
registryService *registry.Service
|
||||||
resourceControlService *resourcecontrol.Service
|
resourceControlService *resourcecontrol.Service
|
||||||
settingsService *settings.Service
|
settingsService *settings.Service
|
||||||
stackService *stack.Service
|
stackService *stack.Service
|
||||||
|
@ -38,6 +40,7 @@ type (
|
||||||
EndpointGroupService *endpointgroup.Service
|
EndpointGroupService *endpointgroup.Service
|
||||||
EndpointService *endpoint.Service
|
EndpointService *endpoint.Service
|
||||||
ExtensionService *extension.Service
|
ExtensionService *extension.Service
|
||||||
|
RegistryService *registry.Service
|
||||||
ResourceControlService *resourcecontrol.Service
|
ResourceControlService *resourcecontrol.Service
|
||||||
SettingsService *settings.Service
|
SettingsService *settings.Service
|
||||||
StackService *stack.Service
|
StackService *stack.Service
|
||||||
|
@ -56,6 +59,7 @@ func NewMigrator(parameters *Parameters) *Migrator {
|
||||||
endpointGroupService: parameters.EndpointGroupService,
|
endpointGroupService: parameters.EndpointGroupService,
|
||||||
endpointService: parameters.EndpointService,
|
endpointService: parameters.EndpointService,
|
||||||
extensionService: parameters.ExtensionService,
|
extensionService: parameters.ExtensionService,
|
||||||
|
registryService: parameters.RegistryService,
|
||||||
resourceControlService: parameters.ResourceControlService,
|
resourceControlService: parameters.ResourceControlService,
|
||||||
settingsService: parameters.SettingsService,
|
settingsService: parameters.SettingsService,
|
||||||
templateService: parameters.TemplateService,
|
templateService: parameters.TemplateService,
|
||||||
|
@ -222,5 +226,28 @@ func (m *Migrator) Migrate() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Portainer 1.21.0
|
||||||
|
if m.currentDBVersion < 18 {
|
||||||
|
err := m.updateUsersToDBVersion18()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.updateEndpointsToDBVersion18()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.updateEndpointGroupsToDBVersion18()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.updateRegistriesToDBVersion18()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return m.versionService.StoreDBVersion(portainer.DBVersion)
|
return m.versionService.StoreDBVersion(portainer.DBVersion)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package registry
|
package registry
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package resourcecontrol
|
package resourcecontrol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package role
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
|
"github.com/boltdb/bolt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// BucketName represents the name of the bucket where this service stores data.
|
||||||
|
BucketName = "roles"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service represents a service for managing endpoint data.
|
||||||
|
type Service struct {
|
||||||
|
db *bolt.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewService creates a new instance of a service.
|
||||||
|
func NewService(db *bolt.DB) (*Service, error) {
|
||||||
|
err := internal.CreateBucket(db, BucketName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Service{
|
||||||
|
db: db,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Role returns a Role by ID
|
||||||
|
func (service *Service) Role(ID portainer.RoleID) (*portainer.Role, error) {
|
||||||
|
var set portainer.Role
|
||||||
|
identifier := internal.Itob(int(ID))
|
||||||
|
|
||||||
|
err := internal.GetObject(service.db, BucketName, identifier, &set)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &set, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roles return an array containing all the sets.
|
||||||
|
func (service *Service) Roles() ([]portainer.Role, error) {
|
||||||
|
var sets = make([]portainer.Role, 0)
|
||||||
|
|
||||||
|
err := service.db.View(func(tx *bolt.Tx) error {
|
||||||
|
bucket := tx.Bucket([]byte(BucketName))
|
||||||
|
|
||||||
|
cursor := bucket.Cursor()
|
||||||
|
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||||
|
var set portainer.Role
|
||||||
|
err := internal.UnmarshalObject(v, &set)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sets = append(sets, set)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return sets, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRole creates a new Role.
|
||||||
|
func (service *Service) CreateRole(set *portainer.Role) error {
|
||||||
|
return service.db.Update(func(tx *bolt.Tx) error {
|
||||||
|
bucket := tx.Bucket([]byte(BucketName))
|
||||||
|
|
||||||
|
id, _ := bucket.NextSequence()
|
||||||
|
set.ID = portainer.RoleID(id)
|
||||||
|
|
||||||
|
data, err := internal.MarshalObject(set)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return bucket.Put(internal.Itob(int(set.ID)), data)
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
package schedule
|
package schedule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package settings
|
package settings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package stack
|
package stack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package tag
|
package tag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package team
|
package team
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package teammembership
|
package teammembership
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package template
|
package template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package webhook
|
package webhook
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt/internal"
|
"github.com/portainer/portainer/api/bolt/internal"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,7 +3,7 @@ package cli
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package main // import "github.com/portainer/portainer"
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -6,20 +6,20 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/bolt"
|
"github.com/portainer/portainer/api/bolt"
|
||||||
"github.com/portainer/portainer/cli"
|
"github.com/portainer/portainer/api/cli"
|
||||||
"github.com/portainer/portainer/cron"
|
"github.com/portainer/portainer/api/cron"
|
||||||
"github.com/portainer/portainer/crypto"
|
"github.com/portainer/portainer/api/crypto"
|
||||||
"github.com/portainer/portainer/docker"
|
"github.com/portainer/portainer/api/docker"
|
||||||
"github.com/portainer/portainer/exec"
|
"github.com/portainer/portainer/api/exec"
|
||||||
"github.com/portainer/portainer/filesystem"
|
"github.com/portainer/portainer/api/filesystem"
|
||||||
"github.com/portainer/portainer/git"
|
"github.com/portainer/portainer/api/git"
|
||||||
"github.com/portainer/portainer/http"
|
"github.com/portainer/portainer/api/http"
|
||||||
"github.com/portainer/portainer/http/client"
|
"github.com/portainer/portainer/api/http/client"
|
||||||
"github.com/portainer/portainer/jwt"
|
"github.com/portainer/portainer/api/jwt"
|
||||||
"github.com/portainer/portainer/ldap"
|
"github.com/portainer/portainer/api/ldap"
|
||||||
"github.com/portainer/portainer/libcompose"
|
"github.com/portainer/portainer/api/libcompose"
|
||||||
|
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
@ -377,18 +377,18 @@ func createTLSSecuredEndpoint(flags *portainer.CLIFlags, endpointService portain
|
||||||
|
|
||||||
endpointID := endpointService.GetNextIdentifier()
|
endpointID := endpointService.GetNextIdentifier()
|
||||||
endpoint := &portainer.Endpoint{
|
endpoint := &portainer.Endpoint{
|
||||||
ID: portainer.EndpointID(endpointID),
|
ID: portainer.EndpointID(endpointID),
|
||||||
Name: "primary",
|
Name: "primary",
|
||||||
URL: *flags.EndpointURL,
|
URL: *flags.EndpointURL,
|
||||||
GroupID: portainer.EndpointGroupID(1),
|
GroupID: portainer.EndpointGroupID(1),
|
||||||
Type: portainer.DockerEnvironment,
|
Type: portainer.DockerEnvironment,
|
||||||
TLSConfig: tlsConfiguration,
|
TLSConfig: tlsConfiguration,
|
||||||
AuthorizedUsers: []portainer.UserID{},
|
UserAccessPolicies: portainer.UserAccessPolicies{},
|
||||||
AuthorizedTeams: []portainer.TeamID{},
|
TeamAccessPolicies: portainer.TeamAccessPolicies{},
|
||||||
Extensions: []portainer.EndpointExtension{},
|
Extensions: []portainer.EndpointExtension{},
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
Status: portainer.EndpointStatusUp,
|
Status: portainer.EndpointStatusUp,
|
||||||
Snapshots: []portainer.Snapshot{},
|
Snapshots: []portainer.Snapshot{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(endpoint.URL, "tcp://") {
|
if strings.HasPrefix(endpoint.URL, "tcp://") {
|
||||||
|
@ -420,18 +420,18 @@ func createUnsecuredEndpoint(endpointURL string, endpointService portainer.Endpo
|
||||||
|
|
||||||
endpointID := endpointService.GetNextIdentifier()
|
endpointID := endpointService.GetNextIdentifier()
|
||||||
endpoint := &portainer.Endpoint{
|
endpoint := &portainer.Endpoint{
|
||||||
ID: portainer.EndpointID(endpointID),
|
ID: portainer.EndpointID(endpointID),
|
||||||
Name: "primary",
|
Name: "primary",
|
||||||
URL: endpointURL,
|
URL: endpointURL,
|
||||||
GroupID: portainer.EndpointGroupID(1),
|
GroupID: portainer.EndpointGroupID(1),
|
||||||
Type: portainer.DockerEnvironment,
|
Type: portainer.DockerEnvironment,
|
||||||
TLSConfig: portainer.TLSConfiguration{},
|
TLSConfig: portainer.TLSConfiguration{},
|
||||||
AuthorizedUsers: []portainer.UserID{},
|
UserAccessPolicies: portainer.UserAccessPolicies{},
|
||||||
AuthorizedTeams: []portainer.TeamID{},
|
TeamAccessPolicies: portainer.TeamAccessPolicies{},
|
||||||
Extensions: []portainer.EndpointExtension{},
|
Extensions: []portainer.EndpointExtension{},
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
Status: portainer.EndpointStatusUp,
|
Status: portainer.EndpointStatusUp,
|
||||||
Snapshots: []portainer.Snapshot{},
|
Snapshots: []portainer.Snapshot{},
|
||||||
}
|
}
|
||||||
|
|
||||||
return snapshotAndPersistEndpoint(endpoint, endpointService, snapshotter)
|
return snapshotAndPersistEndpoint(endpoint, endpointService, snapshotter)
|
||||||
|
@ -627,6 +627,23 @@ func main() {
|
||||||
Username: "admin",
|
Username: "admin",
|
||||||
Role: portainer.AdministratorRole,
|
Role: portainer.AdministratorRole,
|
||||||
Password: adminPasswordHash,
|
Password: adminPasswordHash,
|
||||||
|
PortainerAuthorizations: map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationPortainerDockerHubInspect: true,
|
||||||
|
portainer.OperationPortainerEndpointGroupList: true,
|
||||||
|
portainer.OperationPortainerEndpointList: true,
|
||||||
|
portainer.OperationPortainerEndpointInspect: true,
|
||||||
|
portainer.OperationPortainerEndpointExtensionAdd: true,
|
||||||
|
portainer.OperationPortainerEndpointExtensionRemove: true,
|
||||||
|
portainer.OperationPortainerExtensionList: true,
|
||||||
|
portainer.OperationPortainerMOTD: true,
|
||||||
|
portainer.OperationPortainerRegistryList: true,
|
||||||
|
portainer.OperationPortainerRegistryInspect: true,
|
||||||
|
portainer.OperationPortainerTeamList: true,
|
||||||
|
portainer.OperationPortainerTemplateList: true,
|
||||||
|
portainer.OperationPortainerTemplateInspect: true,
|
||||||
|
portainer.OperationPortainerUserList: true,
|
||||||
|
portainer.OperationPortainerUserMemberships: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
err := store.UserService.CreateUser(user)
|
err := store.UserService.CreateUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -647,6 +664,7 @@ func main() {
|
||||||
AssetsPath: *flags.Assets,
|
AssetsPath: *flags.Assets,
|
||||||
AuthDisabled: *flags.NoAuth,
|
AuthDisabled: *flags.NoAuth,
|
||||||
EndpointManagement: endpointManagement,
|
EndpointManagement: endpointManagement,
|
||||||
|
RoleService: store.RoleService,
|
||||||
UserService: store.UserService,
|
UserService: store.UserService,
|
||||||
TeamService: store.TeamService,
|
TeamService: store.TeamService,
|
||||||
TeamMembershipService: store.TeamMembershipService,
|
TeamMembershipService: store.TeamMembershipService,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EndpointSyncJobRunner is used to run a EndpointSyncJob
|
// EndpointSyncJobRunner is used to run a EndpointSyncJob
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ScriptExecutionJobRunner is used to run a ScriptExecutionJob
|
// ScriptExecutionJobRunner is used to run a ScriptExecutionJob
|
||||||
|
|
|
@ -3,7 +3,7 @@ package cron
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SnapshotJobRunner is used to run a SnapshotJob
|
// SnapshotJobRunner is used to run a SnapshotJob
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package cron
|
package cron
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/robfig/cron"
|
"github.com/robfig/cron"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/crypto"
|
"github.com/portainer/portainer/api/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/api/types/strslice"
|
"github.com/docker/docker/api/types/strslice"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/archive"
|
"github.com/portainer/portainer/api/archive"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JobService represents a service that handles the execution of jobs
|
// JobService represents a service that handles the execution of jobs
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
func snapshot(cli *client.Client) (*portainer.Snapshot, error) {
|
func snapshot(cli *client.Client) (*portainer.Snapshot, error) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Snapshotter represents a service used to create endpoint snapshots
|
// Snapshotter represents a service used to create endpoint snapshots
|
||||||
|
|
|
@ -4,6 +4,7 @@ package portainer
|
||||||
const (
|
const (
|
||||||
ErrUnauthorized = Error("Unauthorized")
|
ErrUnauthorized = Error("Unauthorized")
|
||||||
ErrResourceAccessDenied = Error("Access denied to resource")
|
ErrResourceAccessDenied = Error("Access denied to resource")
|
||||||
|
ErrAuthorizationRequired = Error("Authorization required for this operation")
|
||||||
ErrObjectNotFound = Error("Object not found inside the database")
|
ErrObjectNotFound = Error("Object not found inside the database")
|
||||||
ErrMissingSecurityContext = Error("Unable to find security details in request context")
|
ErrMissingSecurityContext = Error("Unable to find security details in request context")
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,10 +9,11 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/orcaman/concurrent-map"
|
"github.com/orcaman/concurrent-map"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/http/client"
|
"github.com/portainer/portainer/api/http/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
var extensionDownloadBaseURL = "https://portainer-io-assets.sfo2.digitaloceanspaces.com/extensions/"
|
var extensionDownloadBaseURL = "https://portainer-io-assets.sfo2.digitaloceanspaces.com/extensions/"
|
||||||
|
@ -20,6 +21,7 @@ var extensionDownloadBaseURL = "https://portainer-io-assets.sfo2.digitaloceanspa
|
||||||
var extensionBinaryMap = map[portainer.ExtensionID]string{
|
var extensionBinaryMap = map[portainer.ExtensionID]string{
|
||||||
portainer.RegistryManagementExtension: "extension-registry-management",
|
portainer.RegistryManagementExtension: "extension-registry-management",
|
||||||
portainer.OAuthAuthenticationExtension: "extension-oauth-authentication",
|
portainer.OAuthAuthenticationExtension: "extension-oauth-authentication",
|
||||||
|
portainer.RBACExtension: "extension-rbac",
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtensionManager represents a service used to
|
// ExtensionManager represents a service used to
|
||||||
|
@ -206,6 +208,8 @@ func (manager *ExtensionManager) startExtensionProcess(extension *portainer.Exte
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
manager.processes.Set(processKey(extension.ID), extensionProcess)
|
manager.processes.Set(processKey(extension.ID), extensionProcess)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SwarmStackManager represents a service for managing stacks.
|
// SwarmStackManager represents a service for managing stacks.
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/archive"
|
"github.com/portainer/portainer/api/archive"
|
||||||
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type authenticatePayload struct {
|
type authenticatePayload struct {
|
||||||
|
@ -100,6 +100,23 @@ func (handler *Handler) authenticateLDAPAndCreateUser(w http.ResponseWriter, use
|
||||||
user := &portainer.User{
|
user := &portainer.User{
|
||||||
Username: username,
|
Username: username,
|
||||||
Role: portainer.StandardUserRole,
|
Role: portainer.StandardUserRole,
|
||||||
|
PortainerAuthorizations: map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationPortainerDockerHubInspect: true,
|
||||||
|
portainer.OperationPortainerEndpointGroupList: true,
|
||||||
|
portainer.OperationPortainerEndpointList: true,
|
||||||
|
portainer.OperationPortainerEndpointInspect: true,
|
||||||
|
portainer.OperationPortainerEndpointExtensionAdd: true,
|
||||||
|
portainer.OperationPortainerEndpointExtensionRemove: true,
|
||||||
|
portainer.OperationPortainerExtensionList: true,
|
||||||
|
portainer.OperationPortainerMOTD: true,
|
||||||
|
portainer.OperationPortainerRegistryList: true,
|
||||||
|
portainer.OperationPortainerRegistryInspect: true,
|
||||||
|
portainer.OperationPortainerTeamList: true,
|
||||||
|
portainer.OperationPortainerTemplateList: true,
|
||||||
|
portainer.OperationPortainerTemplateInspect: true,
|
||||||
|
portainer.OperationPortainerUserList: true,
|
||||||
|
portainer.OperationPortainerUserMemberships: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.UserService.CreateUser(user)
|
err = handler.UserService.CreateUser(user)
|
||||||
|
@ -117,11 +134,60 @@ func (handler *Handler) authenticateLDAPAndCreateUser(w http.ResponseWriter, use
|
||||||
|
|
||||||
func (handler *Handler) writeToken(w http.ResponseWriter, user *portainer.User) *httperror.HandlerError {
|
func (handler *Handler) writeToken(w http.ResponseWriter, user *portainer.User) *httperror.HandlerError {
|
||||||
tokenData := &portainer.TokenData{
|
tokenData := &portainer.TokenData{
|
||||||
ID: user.ID,
|
ID: user.ID,
|
||||||
Username: user.Username,
|
Username: user.Username,
|
||||||
Role: user.Role,
|
Role: user.Role,
|
||||||
|
PortainerAuthorizations: user.PortainerAuthorizations,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err := handler.ExtensionService.Extension(portainer.RBACExtension)
|
||||||
|
if err == portainer.ErrObjectNotFound {
|
||||||
|
return handler.persistAndWriteToken(w, tokenData)
|
||||||
|
} else if err != nil {
|
||||||
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a extension with the specified identifier inside the database", err}
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointAuthorizations, err := handler.getAuthorizations(user)
|
||||||
|
if err != nil {
|
||||||
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve authorizations associated to the user", err}
|
||||||
|
}
|
||||||
|
tokenData.EndpointAuthorizations = endpointAuthorizations
|
||||||
|
|
||||||
|
return handler.persistAndWriteToken(w, tokenData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *Handler) getAuthorizations(user *portainer.User) (portainer.EndpointAuthorizations, error) {
|
||||||
|
endpointAuthorizations := portainer.EndpointAuthorizations{}
|
||||||
|
if user.Role == portainer.AdministratorRole {
|
||||||
|
return endpointAuthorizations, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
userMemberships, err := handler.TeamMembershipService.TeamMembershipsByUserID(user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return endpointAuthorizations, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints, err := handler.EndpointService.Endpoints()
|
||||||
|
if err != nil {
|
||||||
|
return endpointAuthorizations, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointGroups, err := handler.EndpointGroupService.EndpointGroups()
|
||||||
|
if err != nil {
|
||||||
|
return endpointAuthorizations, err
|
||||||
|
}
|
||||||
|
|
||||||
|
roles, err := handler.RoleService.Roles()
|
||||||
|
if err != nil {
|
||||||
|
return endpointAuthorizations, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointAuthorizations = getUserEndpointAuthorizations(user, endpoints, endpointGroups, roles, userMemberships)
|
||||||
|
|
||||||
|
return endpointAuthorizations, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *Handler) persistAndWriteToken(w http.ResponseWriter, tokenData *portainer.TokenData) *httperror.HandlerError {
|
||||||
token, err := handler.JWTService.GenerateToken(tokenData)
|
token, err := handler.JWTService.GenerateToken(tokenData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to generate JWT token", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to generate JWT token", err}
|
||||||
|
|
|
@ -3,13 +3,13 @@ package auth
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/asaskevich/govalidator"
|
"github.com/asaskevich/govalidator"
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type oauthPayload struct {
|
type oauthPayload struct {
|
||||||
|
@ -113,6 +113,23 @@ func (handler *Handler) validateOAuth(w http.ResponseWriter, r *http.Request) *h
|
||||||
user = &portainer.User{
|
user = &portainer.User{
|
||||||
Username: username,
|
Username: username,
|
||||||
Role: portainer.StandardUserRole,
|
Role: portainer.StandardUserRole,
|
||||||
|
PortainerAuthorizations: map[portainer.Authorization]bool{
|
||||||
|
portainer.OperationPortainerDockerHubInspect: true,
|
||||||
|
portainer.OperationPortainerEndpointGroupList: true,
|
||||||
|
portainer.OperationPortainerEndpointList: true,
|
||||||
|
portainer.OperationPortainerEndpointInspect: true,
|
||||||
|
portainer.OperationPortainerEndpointExtensionAdd: true,
|
||||||
|
portainer.OperationPortainerEndpointExtensionRemove: true,
|
||||||
|
portainer.OperationPortainerExtensionList: true,
|
||||||
|
portainer.OperationPortainerMOTD: true,
|
||||||
|
portainer.OperationPortainerRegistryList: true,
|
||||||
|
portainer.OperationPortainerRegistryInspect: true,
|
||||||
|
portainer.OperationPortainerTeamList: true,
|
||||||
|
portainer.OperationPortainerTemplateList: true,
|
||||||
|
portainer.OperationPortainerTemplateInspect: true,
|
||||||
|
portainer.OperationPortainerUserList: true,
|
||||||
|
portainer.OperationPortainerUserMemberships: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.UserService.CreateUser(user)
|
err = handler.UserService.CreateUser(user)
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import portainer "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
|
func getUserEndpointAuthorizations(user *portainer.User, endpoints []portainer.Endpoint, endpointGroups []portainer.EndpointGroup, roles []portainer.Role, userMemberships []portainer.TeamMembership) portainer.EndpointAuthorizations {
|
||||||
|
endpointAuthorizations := make(portainer.EndpointAuthorizations)
|
||||||
|
|
||||||
|
groupUserAccessPolicies := map[portainer.EndpointGroupID]portainer.UserAccessPolicies{}
|
||||||
|
groupTeamAccessPolicies := map[portainer.EndpointGroupID]portainer.TeamAccessPolicies{}
|
||||||
|
for _, endpointGroup := range endpointGroups {
|
||||||
|
groupUserAccessPolicies[endpointGroup.ID] = endpointGroup.UserAccessPolicies
|
||||||
|
groupTeamAccessPolicies[endpointGroup.ID] = endpointGroup.TeamAccessPolicies
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
authorizations := getAuthorizationsFromUserEndpointPolicy(user, &endpoint, roles)
|
||||||
|
if len(authorizations) > 0 {
|
||||||
|
endpointAuthorizations[endpoint.ID] = authorizations
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
authorizations = getAuthorizationsFromUserEndpointGroupPolicy(user, &endpoint, roles, groupUserAccessPolicies)
|
||||||
|
if len(authorizations) > 0 {
|
||||||
|
endpointAuthorizations[endpoint.ID] = authorizations
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
authorizations = getAuthorizationsFromTeamEndpointPolicies(userMemberships, &endpoint, roles)
|
||||||
|
if len(authorizations) > 0 {
|
||||||
|
endpointAuthorizations[endpoint.ID] = authorizations
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointAuthorizations[endpoint.ID] = getAuthorizationsFromTeamEndpointGroupPolicies(userMemberships, &endpoint, roles, groupTeamAccessPolicies)
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpointAuthorizations
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthorizationsFromUserEndpointPolicy(user *portainer.User, endpoint *portainer.Endpoint, roles []portainer.Role) portainer.Authorizations {
|
||||||
|
policyRoles := make([]portainer.RoleID, 0)
|
||||||
|
|
||||||
|
policy, ok := endpoint.UserAccessPolicies[user.ID]
|
||||||
|
if ok {
|
||||||
|
policyRoles = append(policyRoles, policy.RoleID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAuthorizationsFromRoles(policyRoles, roles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthorizationsFromUserEndpointGroupPolicy(user *portainer.User, endpoint *portainer.Endpoint, roles []portainer.Role, groupAccessPolicies map[portainer.EndpointGroupID]portainer.UserAccessPolicies) portainer.Authorizations {
|
||||||
|
policyRoles := make([]portainer.RoleID, 0)
|
||||||
|
|
||||||
|
policy, ok := groupAccessPolicies[endpoint.GroupID][user.ID]
|
||||||
|
if ok {
|
||||||
|
policyRoles = append(policyRoles, policy.RoleID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAuthorizationsFromRoles(policyRoles, roles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthorizationsFromTeamEndpointPolicies(memberships []portainer.TeamMembership, endpoint *portainer.Endpoint, roles []portainer.Role) portainer.Authorizations {
|
||||||
|
policyRoles := make([]portainer.RoleID, 0)
|
||||||
|
|
||||||
|
for _, membership := range memberships {
|
||||||
|
policy, ok := endpoint.TeamAccessPolicies[membership.TeamID]
|
||||||
|
if ok {
|
||||||
|
policyRoles = append(policyRoles, policy.RoleID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAuthorizationsFromRoles(policyRoles, roles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthorizationsFromTeamEndpointGroupPolicies(memberships []portainer.TeamMembership, endpoint *portainer.Endpoint, roles []portainer.Role, groupAccessPolicies map[portainer.EndpointGroupID]portainer.TeamAccessPolicies) portainer.Authorizations {
|
||||||
|
policyRoles := make([]portainer.RoleID, 0)
|
||||||
|
|
||||||
|
for _, membership := range memberships {
|
||||||
|
policy, ok := groupAccessPolicies[endpoint.GroupID][membership.TeamID]
|
||||||
|
if ok {
|
||||||
|
policyRoles = append(policyRoles, policy.RoleID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAuthorizationsFromRoles(policyRoles, roles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthorizationsFromRoles(roleIdentifiers []portainer.RoleID, roles []portainer.Role) portainer.Authorizations {
|
||||||
|
var roleAuthorizations []portainer.Authorizations
|
||||||
|
for _, id := range roleIdentifiers {
|
||||||
|
for _, role := range roles {
|
||||||
|
if role.ID == id {
|
||||||
|
roleAuthorizations = append(roleAuthorizations, role.Authorizations)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processedAuthorizations := make(portainer.Authorizations)
|
||||||
|
if len(roleAuthorizations) > 0 {
|
||||||
|
processedAuthorizations = roleAuthorizations[0]
|
||||||
|
for idx, authorizations := range roleAuthorizations {
|
||||||
|
if idx == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
processedAuthorizations = mergeAuthorizations(processedAuthorizations, authorizations)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return processedAuthorizations
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeAuthorizations(a, b portainer.Authorizations) portainer.Authorizations {
|
||||||
|
c := make(map[portainer.Authorization]bool)
|
||||||
|
|
||||||
|
for k := range b {
|
||||||
|
if _, ok := a[k]; ok {
|
||||||
|
c[k] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
|
@ -5,9 +5,9 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/http/proxy"
|
"github.com/portainer/portainer/api/http/proxy"
|
||||||
"github.com/portainer/portainer/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -30,6 +30,9 @@ type Handler struct {
|
||||||
TeamService portainer.TeamService
|
TeamService portainer.TeamService
|
||||||
TeamMembershipService portainer.TeamMembershipService
|
TeamMembershipService portainer.TeamMembershipService
|
||||||
ExtensionService portainer.ExtensionService
|
ExtensionService portainer.ExtensionService
|
||||||
|
EndpointService portainer.EndpointService
|
||||||
|
EndpointGroupService portainer.EndpointGroupService
|
||||||
|
RoleService portainer.RoleService
|
||||||
ProxyManager *proxy.Manager
|
ProxyManager *proxy.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type dockerhubUpdatePayload struct {
|
type dockerhubUpdatePayload struct {
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
)
|
)
|
||||||
|
|
||||||
func hideFields(dockerHub *portainer.DockerHub) {
|
func hideFields(dockerHub *portainer.DockerHub) {
|
||||||
|
@ -25,9 +25,9 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
||||||
Router: mux.NewRouter(),
|
Router: mux.NewRouter(),
|
||||||
}
|
}
|
||||||
h.Handle("/dockerhub",
|
h.Handle("/dockerhub",
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.dockerhubInspect))).Methods(http.MethodGet)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.dockerhubInspect))).Methods(http.MethodGet)
|
||||||
h.Handle("/dockerhub",
|
h.Handle("/dockerhub",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.dockerhubUpdate))).Methods(http.MethodPut)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.dockerhubUpdate))).Methods(http.MethodPut)
|
||||||
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type endpointGroupCreatePayload struct {
|
type endpointGroupCreatePayload struct {
|
||||||
|
@ -36,11 +36,11 @@ func (handler *Handler) endpointGroupCreate(w http.ResponseWriter, r *http.Reque
|
||||||
}
|
}
|
||||||
|
|
||||||
endpointGroup := &portainer.EndpointGroup{
|
endpointGroup := &portainer.EndpointGroup{
|
||||||
Name: payload.Name,
|
Name: payload.Name,
|
||||||
Description: payload.Description,
|
Description: payload.Description,
|
||||||
AuthorizedUsers: []portainer.UserID{},
|
UserAccessPolicies: portainer.UserAccessPolicies{},
|
||||||
AuthorizedTeams: []portainer.TeamID{},
|
TeamAccessPolicies: portainer.TeamAccessPolicies{},
|
||||||
Tags: payload.Tags,
|
Tags: payload.Tags,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.EndpointGroupService.CreateEndpointGroup(endpointGroup)
|
err = handler.EndpointGroupService.CreateEndpointGroup(endpointGroup)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DELETE request on /api/endpoint_groups/:id
|
// DELETE request on /api/endpoint_groups/:id
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GET request on /api/endpoint_groups/:id
|
// GET request on /api/endpoint_groups/:id
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
|
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GET request on /api/endpoint_groups
|
// GET request on /api/endpoint_groups
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type endpointGroupUpdatePayload struct {
|
type endpointGroupUpdatePayload struct {
|
||||||
|
@ -14,6 +14,8 @@ type endpointGroupUpdatePayload struct {
|
||||||
Description string
|
Description string
|
||||||
AssociatedEndpoints []portainer.EndpointID
|
AssociatedEndpoints []portainer.EndpointID
|
||||||
Tags []string
|
Tags []string
|
||||||
|
UserAccessPolicies portainer.UserAccessPolicies
|
||||||
|
TeamAccessPolicies portainer.TeamAccessPolicies
|
||||||
}
|
}
|
||||||
|
|
||||||
func (payload *endpointGroupUpdatePayload) Validate(r *http.Request) error {
|
func (payload *endpointGroupUpdatePayload) Validate(r *http.Request) error {
|
||||||
|
@ -52,20 +54,30 @@ func (handler *Handler) endpointGroupUpdate(w http.ResponseWriter, r *http.Reque
|
||||||
endpointGroup.Tags = payload.Tags
|
endpointGroup.Tags = payload.Tags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if payload.UserAccessPolicies != nil {
|
||||||
|
endpointGroup.UserAccessPolicies = payload.UserAccessPolicies
|
||||||
|
}
|
||||||
|
|
||||||
|
if payload.TeamAccessPolicies != nil {
|
||||||
|
endpointGroup.TeamAccessPolicies = payload.TeamAccessPolicies
|
||||||
|
}
|
||||||
|
|
||||||
err = handler.EndpointGroupService.UpdateEndpointGroup(endpointGroup.ID, endpointGroup)
|
err = handler.EndpointGroupService.UpdateEndpointGroup(endpointGroup.ID, endpointGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist endpoint group changes inside the database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist endpoint group changes inside the database", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints, err := handler.EndpointService.Endpoints()
|
if payload.AssociatedEndpoints != nil {
|
||||||
if err != nil {
|
endpoints, err := handler.EndpointService.Endpoints()
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve endpoints from the database", err}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, endpoint := range endpoints {
|
|
||||||
err = handler.updateEndpointGroup(endpoint, portainer.EndpointGroupID(endpointGroupID), payload.AssociatedEndpoints)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to update endpoint", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve endpoints from the database", err}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
err = handler.updateEndpointGroup(endpoint, portainer.EndpointGroupID(endpointGroupID), payload.AssociatedEndpoints)
|
||||||
|
if err != nil {
|
||||||
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to update endpoint", err}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
package endpointgroups
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
httperror "github.com/portainer/libhttp/error"
|
|
||||||
"github.com/portainer/libhttp/request"
|
|
||||||
"github.com/portainer/libhttp/response"
|
|
||||||
"github.com/portainer/portainer"
|
|
||||||
)
|
|
||||||
|
|
||||||
type endpointGroupUpdateAccessPayload struct {
|
|
||||||
AuthorizedUsers []int
|
|
||||||
AuthorizedTeams []int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (payload *endpointGroupUpdateAccessPayload) Validate(r *http.Request) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PUT request on /api/endpoint_groups/:id/access
|
|
||||||
func (handler *Handler) endpointGroupUpdateAccess(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
|
||||||
endpointGroupID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
|
||||||
if err != nil {
|
|
||||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid endpoint group identifier route variable", err}
|
|
||||||
}
|
|
||||||
|
|
||||||
var payload endpointGroupUpdateAccessPayload
|
|
||||||
err = request.DecodeAndValidateJSONPayload(r, &payload)
|
|
||||||
if err != nil {
|
|
||||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid request payload", err}
|
|
||||||
}
|
|
||||||
|
|
||||||
endpointGroup, err := handler.EndpointGroupService.EndpointGroup(portainer.EndpointGroupID(endpointGroupID))
|
|
||||||
if err == portainer.ErrObjectNotFound {
|
|
||||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint group with the specified identifier inside the database", err}
|
|
||||||
} else if err != nil {
|
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint group with the specified identifier inside the database", err}
|
|
||||||
}
|
|
||||||
|
|
||||||
if payload.AuthorizedUsers != nil {
|
|
||||||
authorizedUserIDs := []portainer.UserID{}
|
|
||||||
for _, value := range payload.AuthorizedUsers {
|
|
||||||
authorizedUserIDs = append(authorizedUserIDs, portainer.UserID(value))
|
|
||||||
}
|
|
||||||
endpointGroup.AuthorizedUsers = authorizedUserIDs
|
|
||||||
}
|
|
||||||
|
|
||||||
if payload.AuthorizedTeams != nil {
|
|
||||||
authorizedTeamIDs := []portainer.TeamID{}
|
|
||||||
for _, value := range payload.AuthorizedTeams {
|
|
||||||
authorizedTeamIDs = append(authorizedTeamIDs, portainer.TeamID(value))
|
|
||||||
}
|
|
||||||
endpointGroup.AuthorizedTeams = authorizedTeamIDs
|
|
||||||
}
|
|
||||||
|
|
||||||
err = handler.EndpointGroupService.UpdateEndpointGroup(endpointGroup.ID, endpointGroup)
|
|
||||||
if err != nil {
|
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist endpoint group changes inside the database", err}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.JSON(w, endpointGroup)
|
|
||||||
}
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is the HTTP handler used to handle endpoint group operations.
|
// Handler is the HTTP handler used to handle endpoint group operations.
|
||||||
|
@ -22,17 +22,15 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
||||||
Router: mux.NewRouter(),
|
Router: mux.NewRouter(),
|
||||||
}
|
}
|
||||||
h.Handle("/endpoint_groups",
|
h.Handle("/endpoint_groups",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointGroupCreate))).Methods(http.MethodPost)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointGroupCreate))).Methods(http.MethodPost)
|
||||||
h.Handle("/endpoint_groups",
|
h.Handle("/endpoint_groups",
|
||||||
bouncer.RestrictedAccess(httperror.LoggerHandler(h.endpointGroupList))).Methods(http.MethodGet)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointGroupList))).Methods(http.MethodGet)
|
||||||
h.Handle("/endpoint_groups/{id}",
|
h.Handle("/endpoint_groups/{id}",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointGroupInspect))).Methods(http.MethodGet)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointGroupInspect))).Methods(http.MethodGet)
|
||||||
h.Handle("/endpoint_groups/{id}",
|
h.Handle("/endpoint_groups/{id}",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointGroupUpdate))).Methods(http.MethodPut)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointGroupUpdate))).Methods(http.MethodPut)
|
||||||
h.Handle("/endpoint_groups/{id}/access",
|
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointGroupUpdateAccess))).Methods(http.MethodPut)
|
|
||||||
h.Handle("/endpoint_groups/{id}",
|
h.Handle("/endpoint_groups/{id}",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointGroupDelete))).Methods(http.MethodDelete)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointGroupDelete))).Methods(http.MethodDelete)
|
||||||
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@ package endpointproxy
|
||||||
import (
|
import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/http/proxy"
|
"github.com/portainer/portainer/api/http/proxy"
|
||||||
"github.com/portainer/portainer/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is the HTTP handler used to proxy requests to external APIs.
|
// Handler is the HTTP handler used to proxy requests to external APIs.
|
||||||
|
@ -23,10 +23,10 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
||||||
requestBouncer: bouncer,
|
requestBouncer: bouncer,
|
||||||
}
|
}
|
||||||
h.PathPrefix("/{id}/azure").Handler(
|
h.PathPrefix("/{id}/azure").Handler(
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.proxyRequestsToAzureAPI)))
|
bouncer.RestrictedAccess(httperror.LoggerHandler(h.proxyRequestsToAzureAPI)))
|
||||||
h.PathPrefix("/{id}/docker").Handler(
|
h.PathPrefix("/{id}/docker").Handler(
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.proxyRequestsToDockerAPI)))
|
bouncer.RestrictedAccess(httperror.LoggerHandler(h.proxyRequestsToDockerAPI)))
|
||||||
h.PathPrefix("/{id}/extensions/storidge").Handler(
|
h.PathPrefix("/{id}/storidge").Handler(
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.proxyRequestsToStoridgeAPI)))
|
bouncer.RestrictedAccess(httperror.LoggerHandler(h.proxyRequestsToStoridgeAPI)))
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
|
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
@ -23,9 +23,9 @@ func (handler *Handler) proxyRequestsToAzureAPI(w http.ResponseWriter, r *http.R
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.requestBouncer.EndpointAccess(r, endpoint)
|
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
|
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
var proxy http.Handler
|
var proxy http.Handler
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
@ -28,9 +28,9 @@ func (handler *Handler) proxyRequestsToDockerAPI(w http.ResponseWriter, r *http.
|
||||||
return &httperror.HandlerError{http.StatusServiceUnavailable, "Unable to query endpoint", errors.New("Endpoint is down")}
|
return &httperror.HandlerError{http.StatusServiceUnavailable, "Unable to query endpoint", errors.New("Endpoint is down")}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.requestBouncer.EndpointAccess(r, endpoint)
|
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
|
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
var proxy http.Handler
|
var proxy http.Handler
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
@ -25,9 +25,9 @@ func (handler *Handler) proxyRequestsToStoridgeAPI(w http.ResponseWriter, r *htt
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.requestBouncer.EndpointAccess(r, endpoint)
|
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
|
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
var storidgeExtension *portainer.EndpointExtension
|
var storidgeExtension *portainer.EndpointExtension
|
||||||
|
@ -41,7 +41,7 @@ func (handler *Handler) proxyRequestsToStoridgeAPI(w http.ResponseWriter, r *htt
|
||||||
return &httperror.HandlerError{http.StatusServiceUnavailable, "Storidge extension not supported on this endpoint", portainer.ErrEndpointExtensionNotSupported}
|
return &httperror.HandlerError{http.StatusServiceUnavailable, "Storidge extension not supported on this endpoint", portainer.ErrEndpointExtensionNotSupported}
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyExtensionKey := string(endpoint.ID) + "_" + string(portainer.StoridgeEndpointExtension)
|
proxyExtensionKey := strconv.Itoa(endpointID) + "_" + strconv.Itoa(int(portainer.StoridgeEndpointExtension)) + "_" + storidgeExtension.URL
|
||||||
|
|
||||||
var proxy http.Handler
|
var proxy http.Handler
|
||||||
proxy = handler.ProxyManager.GetLegacyExtensionProxy(proxyExtensionKey)
|
proxy = handler.ProxyManager.GetLegacyExtensionProxy(proxyExtensionKey)
|
||||||
|
@ -53,6 +53,6 @@ func (handler *Handler) proxyRequestsToStoridgeAPI(w http.ResponseWriter, r *htt
|
||||||
}
|
}
|
||||||
|
|
||||||
id := strconv.Itoa(endpointID)
|
id := strconv.Itoa(endpointID)
|
||||||
http.StripPrefix("/"+id+"/extensions/storidge", proxy).ServeHTTP(w, r)
|
http.StripPrefix("/"+id+"/storidge", proxy).ServeHTTP(w, r)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,9 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/crypto"
|
"github.com/portainer/portainer/api/crypto"
|
||||||
"github.com/portainer/portainer/http/client"
|
"github.com/portainer/portainer/api/http/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type endpointCreatePayload struct {
|
type endpointCreatePayload struct {
|
||||||
|
@ -172,19 +172,19 @@ func (handler *Handler) createAzureEndpoint(payload *endpointCreatePayload) (*po
|
||||||
|
|
||||||
endpointID := handler.EndpointService.GetNextIdentifier()
|
endpointID := handler.EndpointService.GetNextIdentifier()
|
||||||
endpoint := &portainer.Endpoint{
|
endpoint := &portainer.Endpoint{
|
||||||
ID: portainer.EndpointID(endpointID),
|
ID: portainer.EndpointID(endpointID),
|
||||||
Name: payload.Name,
|
Name: payload.Name,
|
||||||
URL: "https://management.azure.com",
|
URL: "https://management.azure.com",
|
||||||
Type: portainer.AzureEnvironment,
|
Type: portainer.AzureEnvironment,
|
||||||
GroupID: portainer.EndpointGroupID(payload.GroupID),
|
GroupID: portainer.EndpointGroupID(payload.GroupID),
|
||||||
PublicURL: payload.PublicURL,
|
PublicURL: payload.PublicURL,
|
||||||
AuthorizedUsers: []portainer.UserID{},
|
UserAccessPolicies: portainer.UserAccessPolicies{},
|
||||||
AuthorizedTeams: []portainer.TeamID{},
|
TeamAccessPolicies: portainer.TeamAccessPolicies{},
|
||||||
Extensions: []portainer.EndpointExtension{},
|
Extensions: []portainer.EndpointExtension{},
|
||||||
AzureCredentials: credentials,
|
AzureCredentials: credentials,
|
||||||
Tags: payload.Tags,
|
Tags: payload.Tags,
|
||||||
Status: portainer.EndpointStatusUp,
|
Status: portainer.EndpointStatusUp,
|
||||||
Snapshots: []portainer.Snapshot{},
|
Snapshots: []portainer.Snapshot{},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.EndpointService.CreateEndpoint(endpoint)
|
err = handler.EndpointService.CreateEndpoint(endpoint)
|
||||||
|
@ -224,12 +224,12 @@ func (handler *Handler) createUnsecuredEndpoint(payload *endpointCreatePayload)
|
||||||
TLSConfig: portainer.TLSConfiguration{
|
TLSConfig: portainer.TLSConfiguration{
|
||||||
TLS: false,
|
TLS: false,
|
||||||
},
|
},
|
||||||
AuthorizedUsers: []portainer.UserID{},
|
UserAccessPolicies: portainer.UserAccessPolicies{},
|
||||||
AuthorizedTeams: []portainer.TeamID{},
|
TeamAccessPolicies: portainer.TeamAccessPolicies{},
|
||||||
Extensions: []portainer.EndpointExtension{},
|
Extensions: []portainer.EndpointExtension{},
|
||||||
Tags: payload.Tags,
|
Tags: payload.Tags,
|
||||||
Status: portainer.EndpointStatusUp,
|
Status: portainer.EndpointStatusUp,
|
||||||
Snapshots: []portainer.Snapshot{},
|
Snapshots: []portainer.Snapshot{},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := handler.snapshotAndPersistEndpoint(endpoint)
|
err := handler.snapshotAndPersistEndpoint(endpoint)
|
||||||
|
@ -268,12 +268,12 @@ func (handler *Handler) createTLSSecuredEndpoint(payload *endpointCreatePayload)
|
||||||
TLS: payload.TLS,
|
TLS: payload.TLS,
|
||||||
TLSSkipVerify: payload.TLSSkipVerify,
|
TLSSkipVerify: payload.TLSSkipVerify,
|
||||||
},
|
},
|
||||||
AuthorizedUsers: []portainer.UserID{},
|
UserAccessPolicies: portainer.UserAccessPolicies{},
|
||||||
AuthorizedTeams: []portainer.TeamID{},
|
TeamAccessPolicies: portainer.TeamAccessPolicies{},
|
||||||
Extensions: []portainer.EndpointExtension{},
|
Extensions: []portainer.EndpointExtension{},
|
||||||
Tags: payload.Tags,
|
Tags: payload.Tags,
|
||||||
Status: portainer.EndpointStatusUp,
|
Status: portainer.EndpointStatusUp,
|
||||||
Snapshots: []portainer.Snapshot{},
|
Snapshots: []portainer.Snapshot{},
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystemError := handler.storeTLSFiles(endpoint, payload)
|
filesystemError := handler.storeTLSFiles(endpoint, payload)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DELETE request on /api/endpoints/:id
|
// DELETE request on /api/endpoints/:id
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type endpointExtensionAddPayload struct {
|
type endpointExtensionAddPayload struct {
|
||||||
|
@ -50,9 +50,9 @@ func (handler *Handler) endpointExtensionAdd(w http.ResponseWriter, r *http.Requ
|
||||||
extensionType := portainer.EndpointExtensionType(payload.Type)
|
extensionType := portainer.EndpointExtensionType(payload.Type)
|
||||||
|
|
||||||
var extension *portainer.EndpointExtension
|
var extension *portainer.EndpointExtension
|
||||||
for _, ext := range endpoint.Extensions {
|
for idx := range endpoint.Extensions {
|
||||||
if ext.Type == extensionType {
|
if endpoint.Extensions[idx].Type == extensionType {
|
||||||
extension = &ext
|
extension = &endpoint.Extensions[idx]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DELETE request on /api/endpoints/:id/extensions/:extensionType
|
// DELETE request on /api/endpoints/:id/extensions/:extensionType
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GET request on /api/endpoints/:id
|
// GET request on /api/endpoints/:id
|
||||||
|
@ -23,9 +23,9 @@ func (handler *Handler) endpointInspect(w http.ResponseWriter, r *http.Request)
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.requestBouncer.EndpointAccess(r, endpoint)
|
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
|
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
hideFields(endpoint)
|
hideFields(endpoint)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type endpointJobFromFilePayload struct {
|
type endpointJobFromFilePayload struct {
|
||||||
|
@ -70,11 +70,6 @@ func (handler *Handler) endpointJob(w http.ResponseWriter, r *http.Request) *htt
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.requestBouncer.EndpointAccess(r, endpoint)
|
|
||||||
if err != nil {
|
|
||||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch method {
|
switch method {
|
||||||
case "file":
|
case "file":
|
||||||
return handler.executeJobFromFile(w, r, endpoint, nodeName)
|
return handler.executeJobFromFile(w, r, endpoint, nodeName)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
|
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GET request on /api/endpoints
|
// GET request on /api/endpoints
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// POST request on /api/endpoints/:id/snapshot
|
// POST request on /api/endpoints/:id/snapshot
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// POST request on /api/endpoints/snapshot
|
// POST request on /api/endpoints/snapshot
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/http/client"
|
"github.com/portainer/portainer/api/http/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type endpointUpdatePayload struct {
|
type endpointUpdatePayload struct {
|
||||||
|
@ -24,6 +24,8 @@ type endpointUpdatePayload struct {
|
||||||
AzureTenantID *string
|
AzureTenantID *string
|
||||||
AzureAuthenticationKey *string
|
AzureAuthenticationKey *string
|
||||||
Tags []string
|
Tags []string
|
||||||
|
UserAccessPolicies portainer.UserAccessPolicies
|
||||||
|
TeamAccessPolicies portainer.TeamAccessPolicies
|
||||||
}
|
}
|
||||||
|
|
||||||
func (payload *endpointUpdatePayload) Validate(r *http.Request) error {
|
func (payload *endpointUpdatePayload) Validate(r *http.Request) error {
|
||||||
|
@ -74,6 +76,14 @@ func (handler *Handler) endpointUpdate(w http.ResponseWriter, r *http.Request) *
|
||||||
endpoint.Tags = payload.Tags
|
endpoint.Tags = payload.Tags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if payload.UserAccessPolicies != nil {
|
||||||
|
endpoint.UserAccessPolicies = payload.UserAccessPolicies
|
||||||
|
}
|
||||||
|
|
||||||
|
if payload.TeamAccessPolicies != nil {
|
||||||
|
endpoint.TeamAccessPolicies = payload.TeamAccessPolicies
|
||||||
|
}
|
||||||
|
|
||||||
if payload.Status != nil {
|
if payload.Status != nil {
|
||||||
switch *payload.Status {
|
switch *payload.Status {
|
||||||
case 1:
|
case 1:
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
package endpoints
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
httperror "github.com/portainer/libhttp/error"
|
|
||||||
"github.com/portainer/libhttp/request"
|
|
||||||
"github.com/portainer/libhttp/response"
|
|
||||||
"github.com/portainer/portainer"
|
|
||||||
)
|
|
||||||
|
|
||||||
type endpointUpdateAccessPayload struct {
|
|
||||||
AuthorizedUsers []int
|
|
||||||
AuthorizedTeams []int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (payload *endpointUpdateAccessPayload) Validate(r *http.Request) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PUT request on /api/endpoints/:id/access
|
|
||||||
func (handler *Handler) endpointUpdateAccess(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
|
||||||
if !handler.authorizeEndpointManagement {
|
|
||||||
return &httperror.HandlerError{http.StatusServiceUnavailable, "Endpoint management is disabled", ErrEndpointManagementDisabled}
|
|
||||||
}
|
|
||||||
|
|
||||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
|
||||||
if err != nil {
|
|
||||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid endpoint identifier route variable", err}
|
|
||||||
}
|
|
||||||
|
|
||||||
var payload endpointUpdateAccessPayload
|
|
||||||
err = request.DecodeAndValidateJSONPayload(r, &payload)
|
|
||||||
if err != nil {
|
|
||||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid request payload", err}
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoint, err := handler.EndpointService.Endpoint(portainer.EndpointID(endpointID))
|
|
||||||
if err == portainer.ErrObjectNotFound {
|
|
||||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find an endpoint with the specified identifier inside the database", err}
|
|
||||||
} else if err != nil {
|
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
|
||||||
}
|
|
||||||
|
|
||||||
if payload.AuthorizedUsers != nil {
|
|
||||||
authorizedUserIDs := []portainer.UserID{}
|
|
||||||
for _, value := range payload.AuthorizedUsers {
|
|
||||||
authorizedUserIDs = append(authorizedUserIDs, portainer.UserID(value))
|
|
||||||
}
|
|
||||||
endpoint.AuthorizedUsers = authorizedUserIDs
|
|
||||||
}
|
|
||||||
|
|
||||||
if payload.AuthorizedTeams != nil {
|
|
||||||
authorizedTeamIDs := []portainer.TeamID{}
|
|
||||||
for _, value := range payload.AuthorizedTeams {
|
|
||||||
authorizedTeamIDs = append(authorizedTeamIDs, portainer.TeamID(value))
|
|
||||||
}
|
|
||||||
endpoint.AuthorizedTeams = authorizedTeamIDs
|
|
||||||
}
|
|
||||||
|
|
||||||
err = handler.EndpointService.UpdateEndpoint(endpoint.ID, endpoint)
|
|
||||||
if err != nil {
|
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist endpoint changes inside the database", err}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.JSON(w, endpoint)
|
|
||||||
}
|
|
|
@ -2,9 +2,9 @@ package endpoints
|
||||||
|
|
||||||
import (
|
import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/http/proxy"
|
"github.com/portainer/portainer/api/http/proxy"
|
||||||
"github.com/portainer/portainer/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -37,32 +37,30 @@ type Handler struct {
|
||||||
// NewHandler creates a handler to manage endpoint operations.
|
// NewHandler creates a handler to manage endpoint operations.
|
||||||
func NewHandler(bouncer *security.RequestBouncer, authorizeEndpointManagement bool) *Handler {
|
func NewHandler(bouncer *security.RequestBouncer, authorizeEndpointManagement bool) *Handler {
|
||||||
h := &Handler{
|
h := &Handler{
|
||||||
Router: mux.NewRouter(),
|
Router: mux.NewRouter(),
|
||||||
authorizeEndpointManagement: authorizeEndpointManagement,
|
authorizeEndpointManagement: authorizeEndpointManagement,
|
||||||
requestBouncer: bouncer,
|
requestBouncer: bouncer,
|
||||||
}
|
}
|
||||||
|
|
||||||
h.Handle("/endpoints",
|
h.Handle("/endpoints",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointCreate))).Methods(http.MethodPost)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointCreate))).Methods(http.MethodPost)
|
||||||
h.Handle("/endpoints/snapshot",
|
h.Handle("/endpoints/snapshot",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointSnapshots))).Methods(http.MethodPost)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointSnapshots))).Methods(http.MethodPost)
|
||||||
h.Handle("/endpoints",
|
h.Handle("/endpoints",
|
||||||
bouncer.RestrictedAccess(httperror.LoggerHandler(h.endpointList))).Methods(http.MethodGet)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointList))).Methods(http.MethodGet)
|
||||||
h.Handle("/endpoints/{id}",
|
h.Handle("/endpoints/{id}",
|
||||||
bouncer.RestrictedAccess(httperror.LoggerHandler(h.endpointInspect))).Methods(http.MethodGet)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointInspect))).Methods(http.MethodGet)
|
||||||
h.Handle("/endpoints/{id}",
|
h.Handle("/endpoints/{id}",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointUpdate))).Methods(http.MethodPut)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointUpdate))).Methods(http.MethodPut)
|
||||||
h.Handle("/endpoints/{id}/access",
|
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointUpdateAccess))).Methods(http.MethodPut)
|
|
||||||
h.Handle("/endpoints/{id}",
|
h.Handle("/endpoints/{id}",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointDelete))).Methods(http.MethodDelete)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointDelete))).Methods(http.MethodDelete)
|
||||||
h.Handle("/endpoints/{id}/extensions",
|
h.Handle("/endpoints/{id}/extensions",
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.endpointExtensionAdd))).Methods(http.MethodPost)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointExtensionAdd))).Methods(http.MethodPost)
|
||||||
h.Handle("/endpoints/{id}/extensions/{extensionType}",
|
h.Handle("/endpoints/{id}/extensions/{extensionType}",
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.endpointExtensionRemove))).Methods(http.MethodDelete)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointExtensionRemove))).Methods(http.MethodDelete)
|
||||||
h.Handle("/endpoints/{id}/job",
|
h.Handle("/endpoints/{id}/job",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointJob))).Methods(http.MethodPost)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointJob))).Methods(http.MethodPost)
|
||||||
h.Handle("/endpoints/{id}/snapshot",
|
h.Handle("/endpoints/{id}/snapshot",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointSnapshot))).Methods(http.MethodPost)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.endpointSnapshot))).Methods(http.MethodPost)
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type extensionCreatePayload struct {
|
type extensionCreatePayload struct {
|
||||||
|
@ -70,6 +70,13 @@ func (handler *Handler) extensionCreate(w http.ResponseWriter, r *http.Request)
|
||||||
|
|
||||||
extension.Enabled = true
|
extension.Enabled = true
|
||||||
|
|
||||||
|
if extension.ID == portainer.RBACExtension {
|
||||||
|
err = handler.upgradeRBACData()
|
||||||
|
if err != nil {
|
||||||
|
return &httperror.HandlerError{http.StatusInternalServerError, "An error occured during database update", err}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = handler.ExtensionService.Persist(extension)
|
err = handler.ExtensionService.Persist(extension)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist extension status inside the database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist extension status inside the database", err}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DELETE request on /api/extensions/:id
|
// DELETE request on /api/extensions/:id
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/http/client"
|
"github.com/portainer/portainer/api/http/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GET request on /api/extensions/:id
|
// GET request on /api/extensions/:id
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GET request on /api/extensions?store=<store>
|
// GET request on /api/extensions?store=<store>
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type extensionUpdatePayload struct {
|
type extensionUpdatePayload struct {
|
||||||
|
|
|
@ -5,15 +5,18 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is the HTTP handler used to handle extension operations.
|
// Handler is the HTTP handler used to handle extension operations.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
*mux.Router
|
*mux.Router
|
||||||
ExtensionService portainer.ExtensionService
|
ExtensionService portainer.ExtensionService
|
||||||
ExtensionManager portainer.ExtensionManager
|
ExtensionManager portainer.ExtensionManager
|
||||||
|
EndpointGroupService portainer.EndpointGroupService
|
||||||
|
EndpointService portainer.EndpointService
|
||||||
|
RegistryService portainer.RegistryService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler creates a handler to manage extension operations.
|
// NewHandler creates a handler to manage extension operations.
|
||||||
|
@ -23,15 +26,15 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
h.Handle("/extensions",
|
h.Handle("/extensions",
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.extensionList))).Methods(http.MethodGet)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.extensionList))).Methods(http.MethodGet)
|
||||||
h.Handle("/extensions",
|
h.Handle("/extensions",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.extensionCreate))).Methods(http.MethodPost)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.extensionCreate))).Methods(http.MethodPost)
|
||||||
h.Handle("/extensions/{id}",
|
h.Handle("/extensions/{id}",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.extensionInspect))).Methods(http.MethodGet)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.extensionInspect))).Methods(http.MethodGet)
|
||||||
h.Handle("/extensions/{id}",
|
h.Handle("/extensions/{id}",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.extensionDelete))).Methods(http.MethodDelete)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.extensionDelete))).Methods(http.MethodDelete)
|
||||||
h.Handle("/extensions/{id}/update",
|
h.Handle("/extensions/{id}/update",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.extensionUpdate))).Methods(http.MethodPost)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.extensionUpdate))).Methods(http.MethodPost)
|
||||||
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package extensions
|
||||||
|
|
||||||
|
import portainer "github.com/portainer/portainer/api"
|
||||||
|
|
||||||
|
func updateUserAccessPolicyToReadOnlyRole(policies portainer.UserAccessPolicies, key portainer.UserID) {
|
||||||
|
tmp := policies[key]
|
||||||
|
tmp.RoleID = 4
|
||||||
|
policies[key] = tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateTeamAccessPolicyToReadOnlyRole(policies portainer.TeamAccessPolicies, key portainer.TeamID) {
|
||||||
|
tmp := policies[key]
|
||||||
|
tmp.RoleID = 4
|
||||||
|
policies[key] = tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *Handler) upgradeRBACData() error {
|
||||||
|
endpointGroups, err := handler.EndpointGroupService.EndpointGroups()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpointGroup := range endpointGroups {
|
||||||
|
for key := range endpointGroup.UserAccessPolicies {
|
||||||
|
updateUserAccessPolicyToReadOnlyRole(endpointGroup.UserAccessPolicies, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
for key := range endpointGroup.TeamAccessPolicies {
|
||||||
|
updateTeamAccessPolicyToReadOnlyRole(endpointGroup.TeamAccessPolicies, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := handler.EndpointGroupService.UpdateEndpointGroup(endpointGroup.ID, &endpointGroup)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints, err := handler.EndpointService.Endpoints()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
for key := range endpoint.UserAccessPolicies {
|
||||||
|
updateUserAccessPolicyToReadOnlyRole(endpoint.UserAccessPolicies, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
for key := range endpoint.TeamAccessPolicies {
|
||||||
|
updateTeamAccessPolicyToReadOnlyRole(endpoint.TeamAccessPolicies, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := handler.EndpointService.UpdateEndpoint(endpoint.ID, &endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -4,34 +4,36 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/portainer/portainer/http/handler/auth"
|
"github.com/portainer/portainer/api/http/handler/schedules"
|
||||||
"github.com/portainer/portainer/http/handler/dockerhub"
|
|
||||||
"github.com/portainer/portainer/http/handler/endpointgroups"
|
"github.com/portainer/portainer/api/http/handler/roles"
|
||||||
"github.com/portainer/portainer/http/handler/endpointproxy"
|
|
||||||
"github.com/portainer/portainer/http/handler/endpoints"
|
"github.com/portainer/portainer/api/http/handler/auth"
|
||||||
"github.com/portainer/portainer/http/handler/extensions"
|
"github.com/portainer/portainer/api/http/handler/dockerhub"
|
||||||
"github.com/portainer/portainer/http/handler/file"
|
"github.com/portainer/portainer/api/http/handler/endpointgroups"
|
||||||
"github.com/portainer/portainer/http/handler/motd"
|
"github.com/portainer/portainer/api/http/handler/endpointproxy"
|
||||||
"github.com/portainer/portainer/http/handler/registries"
|
"github.com/portainer/portainer/api/http/handler/endpoints"
|
||||||
"github.com/portainer/portainer/http/handler/resourcecontrols"
|
"github.com/portainer/portainer/api/http/handler/extensions"
|
||||||
"github.com/portainer/portainer/http/handler/schedules"
|
"github.com/portainer/portainer/api/http/handler/file"
|
||||||
"github.com/portainer/portainer/http/handler/settings"
|
"github.com/portainer/portainer/api/http/handler/motd"
|
||||||
"github.com/portainer/portainer/http/handler/stacks"
|
"github.com/portainer/portainer/api/http/handler/registries"
|
||||||
"github.com/portainer/portainer/http/handler/status"
|
"github.com/portainer/portainer/api/http/handler/resourcecontrols"
|
||||||
"github.com/portainer/portainer/http/handler/tags"
|
"github.com/portainer/portainer/api/http/handler/settings"
|
||||||
"github.com/portainer/portainer/http/handler/teammemberships"
|
"github.com/portainer/portainer/api/http/handler/stacks"
|
||||||
"github.com/portainer/portainer/http/handler/teams"
|
"github.com/portainer/portainer/api/http/handler/status"
|
||||||
"github.com/portainer/portainer/http/handler/templates"
|
"github.com/portainer/portainer/api/http/handler/tags"
|
||||||
"github.com/portainer/portainer/http/handler/upload"
|
"github.com/portainer/portainer/api/http/handler/teammemberships"
|
||||||
"github.com/portainer/portainer/http/handler/users"
|
"github.com/portainer/portainer/api/http/handler/teams"
|
||||||
"github.com/portainer/portainer/http/handler/webhooks"
|
"github.com/portainer/portainer/api/http/handler/templates"
|
||||||
"github.com/portainer/portainer/http/handler/websocket"
|
"github.com/portainer/portainer/api/http/handler/upload"
|
||||||
|
"github.com/portainer/portainer/api/http/handler/users"
|
||||||
|
"github.com/portainer/portainer/api/http/handler/webhooks"
|
||||||
|
"github.com/portainer/portainer/api/http/handler/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is a collection of all the service handlers.
|
// Handler is a collection of all the service handlers.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
AuthHandler *auth.Handler
|
AuthHandler *auth.Handler
|
||||||
|
|
||||||
DockerHubHandler *dockerhub.Handler
|
DockerHubHandler *dockerhub.Handler
|
||||||
EndpointGroupHandler *endpointgroups.Handler
|
EndpointGroupHandler *endpointgroups.Handler
|
||||||
EndpointHandler *endpoints.Handler
|
EndpointHandler *endpoints.Handler
|
||||||
|
@ -41,6 +43,8 @@ type Handler struct {
|
||||||
ExtensionHandler *extensions.Handler
|
ExtensionHandler *extensions.Handler
|
||||||
RegistryHandler *registries.Handler
|
RegistryHandler *registries.Handler
|
||||||
ResourceControlHandler *resourcecontrols.Handler
|
ResourceControlHandler *resourcecontrols.Handler
|
||||||
|
RoleHandler *roles.Handler
|
||||||
|
SchedulesHanlder *schedules.Handler
|
||||||
SettingsHandler *settings.Handler
|
SettingsHandler *settings.Handler
|
||||||
StackHandler *stacks.Handler
|
StackHandler *stacks.Handler
|
||||||
StatusHandler *status.Handler
|
StatusHandler *status.Handler
|
||||||
|
@ -52,7 +56,6 @@ type Handler struct {
|
||||||
UserHandler *users.Handler
|
UserHandler *users.Handler
|
||||||
WebSocketHandler *websocket.Handler
|
WebSocketHandler *websocket.Handler
|
||||||
WebhookHandler *webhooks.Handler
|
WebhookHandler *webhooks.Handler
|
||||||
SchedulesHanlder *schedules.Handler
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeHTTP delegates a request to the appropriate subhandler.
|
// ServeHTTP delegates a request to the appropriate subhandler.
|
||||||
|
@ -68,21 +71,25 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
switch {
|
switch {
|
||||||
case strings.Contains(r.URL.Path, "/docker/"):
|
case strings.Contains(r.URL.Path, "/docker/"):
|
||||||
http.StripPrefix("/api/endpoints", h.EndpointProxyHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api/endpoints", h.EndpointProxyHandler).ServeHTTP(w, r)
|
||||||
case strings.Contains(r.URL.Path, "/extensions/storidge"):
|
case strings.Contains(r.URL.Path, "/storidge/"):
|
||||||
http.StripPrefix("/api/endpoints", h.EndpointProxyHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api/endpoints", h.EndpointProxyHandler).ServeHTTP(w, r)
|
||||||
case strings.Contains(r.URL.Path, "/azure/"):
|
case strings.Contains(r.URL.Path, "/azure/"):
|
||||||
http.StripPrefix("/api/endpoints", h.EndpointProxyHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api/endpoints", h.EndpointProxyHandler).ServeHTTP(w, r)
|
||||||
default:
|
default:
|
||||||
http.StripPrefix("/api", h.EndpointHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.EndpointHandler).ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
case strings.HasPrefix(r.URL.Path, "/api/motd"):
|
|
||||||
http.StripPrefix("/api", h.MOTDHandler).ServeHTTP(w, r)
|
|
||||||
case strings.HasPrefix(r.URL.Path, "/api/extensions"):
|
case strings.HasPrefix(r.URL.Path, "/api/extensions"):
|
||||||
http.StripPrefix("/api", h.ExtensionHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.ExtensionHandler).ServeHTTP(w, r)
|
||||||
|
case strings.HasPrefix(r.URL.Path, "/api/motd"):
|
||||||
|
http.StripPrefix("/api", h.MOTDHandler).ServeHTTP(w, r)
|
||||||
case strings.HasPrefix(r.URL.Path, "/api/registries"):
|
case strings.HasPrefix(r.URL.Path, "/api/registries"):
|
||||||
http.StripPrefix("/api", h.RegistryHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.RegistryHandler).ServeHTTP(w, r)
|
||||||
case strings.HasPrefix(r.URL.Path, "/api/resource_controls"):
|
case strings.HasPrefix(r.URL.Path, "/api/resource_controls"):
|
||||||
http.StripPrefix("/api", h.ResourceControlHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.ResourceControlHandler).ServeHTTP(w, r)
|
||||||
|
case strings.HasPrefix(r.URL.Path, "/api/roles"):
|
||||||
|
http.StripPrefix("/api", h.RoleHandler).ServeHTTP(w, r)
|
||||||
|
case strings.HasPrefix(r.URL.Path, "/api/schedules"):
|
||||||
|
http.StripPrefix("/api", h.SchedulesHanlder).ServeHTTP(w, r)
|
||||||
case strings.HasPrefix(r.URL.Path, "/api/settings"):
|
case strings.HasPrefix(r.URL.Path, "/api/settings"):
|
||||||
http.StripPrefix("/api", h.SettingsHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.SettingsHandler).ServeHTTP(w, r)
|
||||||
case strings.HasPrefix(r.URL.Path, "/api/stacks"):
|
case strings.HasPrefix(r.URL.Path, "/api/stacks"):
|
||||||
|
@ -105,8 +112,6 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
http.StripPrefix("/api", h.WebSocketHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.WebSocketHandler).ServeHTTP(w, r)
|
||||||
case strings.HasPrefix(r.URL.Path, "/api/webhooks"):
|
case strings.HasPrefix(r.URL.Path, "/api/webhooks"):
|
||||||
http.StripPrefix("/api", h.WebhookHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.WebhookHandler).ServeHTTP(w, r)
|
||||||
case strings.HasPrefix(r.URL.Path, "/api/schedules"):
|
|
||||||
http.StripPrefix("/api", h.SchedulesHanlder).ServeHTTP(w, r)
|
|
||||||
case strings.HasPrefix(r.URL.Path, "/"):
|
case strings.HasPrefix(r.URL.Path, "/"):
|
||||||
h.FileHandler.ServeHTTP(w, r)
|
h.FileHandler.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/portainer/portainer/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is the HTTP handler used to handle MOTD operations.
|
// Handler is the HTTP handler used to handle MOTD operations.
|
||||||
|
@ -18,7 +18,7 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
||||||
Router: mux.NewRouter(),
|
Router: mux.NewRouter(),
|
||||||
}
|
}
|
||||||
h.Handle("/motd",
|
h.Handle("/motd",
|
||||||
bouncer.AuthenticatedAccess(http.HandlerFunc(h.motd))).Methods(http.MethodGet)
|
bouncer.AuthorizedAccess(http.HandlerFunc(h.motd))).Methods(http.MethodGet)
|
||||||
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,55 @@
|
||||||
package motd
|
package motd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/crypto"
|
"github.com/portainer/portainer/api/crypto"
|
||||||
"github.com/portainer/portainer/http/client"
|
"github.com/portainer/portainer/api/http/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type motdResponse struct {
|
type motdResponse struct {
|
||||||
Title string `json:"Title"`
|
Title string `json:"Title"`
|
||||||
Message string `json:"Message"`
|
Message string `json:"Message"`
|
||||||
Hash []byte `json:"Hash"`
|
ContentLayout map[string]string `json:"ContentLayout"`
|
||||||
|
Style string `json:"Style"`
|
||||||
|
Hash []byte `json:"Hash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type motdData struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Message []string `json:"message"`
|
||||||
|
ContentLayout map[string]string `json:"contentLayout"`
|
||||||
|
Style string `json:"style"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *Handler) motd(w http.ResponseWriter, r *http.Request) {
|
func (handler *Handler) motd(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
motd, err := client.Get(portainer.MessageOfTheDayURL, 0)
|
motd, err := client.Get(portainer.MessageOfTheDayURL, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.JSON(w, &motdResponse{Message: ""})
|
response.JSON(w, &motdResponse{Message: ""})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
title, err := client.Get(portainer.MessageOfTheDayTitleURL, 0)
|
var data motdData
|
||||||
|
err = json.Unmarshal(motd, &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.JSON(w, &motdResponse{Message: ""})
|
response.JSON(w, &motdResponse{Message: ""})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := crypto.HashFromBytes(motd)
|
message := strings.Join(data.Message, "\n")
|
||||||
response.JSON(w, &motdResponse{Title: string(title), Message: string(motd), Hash: hash})
|
|
||||||
|
hash := crypto.HashFromBytes([]byte(message))
|
||||||
|
resp := motdResponse{
|
||||||
|
Title: data.Title,
|
||||||
|
Message: message,
|
||||||
|
Hash: hash,
|
||||||
|
ContentLayout: data.ContentLayout,
|
||||||
|
Style: data.Style,
|
||||||
|
}
|
||||||
|
|
||||||
|
response.JSON(w, &resp)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,9 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/http/proxy"
|
"github.com/portainer/portainer/api/http/proxy"
|
||||||
"github.com/portainer/portainer/http/security"
|
"github.com/portainer/portainer/api/http/security"
|
||||||
)
|
)
|
||||||
|
|
||||||
func hideFields(registry *portainer.Registry) {
|
func hideFields(registry *portainer.Registry) {
|
||||||
|
@ -33,19 +33,17 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
h.Handle("/registries",
|
h.Handle("/registries",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.registryCreate))).Methods(http.MethodPost)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.registryCreate))).Methods(http.MethodPost)
|
||||||
h.Handle("/registries",
|
h.Handle("/registries",
|
||||||
bouncer.RestrictedAccess(httperror.LoggerHandler(h.registryList))).Methods(http.MethodGet)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.registryList))).Methods(http.MethodGet)
|
||||||
h.Handle("/registries/{id}",
|
h.Handle("/registries/{id}",
|
||||||
bouncer.RestrictedAccess(httperror.LoggerHandler(h.registryInspect))).Methods(http.MethodGet)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.registryInspect))).Methods(http.MethodGet)
|
||||||
h.Handle("/registries/{id}",
|
h.Handle("/registries/{id}",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.registryUpdate))).Methods(http.MethodPut)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.registryUpdate))).Methods(http.MethodPut)
|
||||||
h.Handle("/registries/{id}/access",
|
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.registryUpdateAccess))).Methods(http.MethodPut)
|
|
||||||
h.Handle("/registries/{id}/configure",
|
h.Handle("/registries/{id}/configure",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.registryConfigure))).Methods(http.MethodPost)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.registryConfigure))).Methods(http.MethodPost)
|
||||||
h.Handle("/registries/{id}",
|
h.Handle("/registries/{id}",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.registryDelete))).Methods(http.MethodDelete)
|
bouncer.AuthorizedAccess(httperror.LoggerHandler(h.registryDelete))).Methods(http.MethodDelete)
|
||||||
h.PathPrefix("/registries/{id}/v2").Handler(
|
h.PathPrefix("/registries/{id}/v2").Handler(
|
||||||
bouncer.RestrictedAccess(httperror.LoggerHandler(h.proxyRequestsToRegistryAPI)))
|
bouncer.RestrictedAccess(httperror.LoggerHandler(h.proxyRequestsToRegistryAPI)))
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// request on /api/registries/:id/v2
|
// request on /api/registries/:id/v2
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type registryConfigurePayload struct {
|
type registryConfigurePayload struct {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
httperror "github.com/portainer/libhttp/error"
|
httperror "github.com/portainer/libhttp/error"
|
||||||
"github.com/portainer/libhttp/request"
|
"github.com/portainer/libhttp/request"
|
||||||
"github.com/portainer/libhttp/response"
|
"github.com/portainer/libhttp/response"
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type registryCreatePayload struct {
|
type registryCreatePayload struct {
|
||||||
|
@ -53,14 +53,14 @@ func (handler *Handler) registryCreate(w http.ResponseWriter, r *http.Request) *
|
||||||
}
|
}
|
||||||
|
|
||||||
registry := &portainer.Registry{
|
registry := &portainer.Registry{
|
||||||
Type: portainer.RegistryType(payload.Type),
|
Type: portainer.RegistryType(payload.Type),
|
||||||
Name: payload.Name,
|
Name: payload.Name,
|
||||||
URL: payload.URL,
|
URL: payload.URL,
|
||||||
Authentication: payload.Authentication,
|
Authentication: payload.Authentication,
|
||||||
Username: payload.Username,
|
Username: payload.Username,
|
||||||
Password: payload.Password,
|
Password: payload.Password,
|
||||||
AuthorizedUsers: []portainer.UserID{},
|
UserAccessPolicies: portainer.UserAccessPolicies{},
|
||||||
AuthorizedTeams: []portainer.TeamID{},
|
TeamAccessPolicies: portainer.TeamAccessPolicies{},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.RegistryService.CreateRegistry(registry)
|
err = handler.RegistryService.CreateRegistry(registry)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue