diff --git a/app/assets/javascripts/app/controllers/api.coffee b/app/assets/javascripts/app/controllers/api.coffee
new file mode 100644
index 000000000..fcba593c3
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/api.coffee
@@ -0,0 +1,112 @@
+class Index extends App.ControllerContent
+ requiredPermission: 'admin.api'
+ events:
+ 'click .action': 'action'
+ 'change .js-TokenAccess input': 'toggleTokenAccess'
+ 'change .js-PasswordAccess input': 'togglePasswordAccess'
+ 'click .js-appNew': 'appNew'
+
+ elements:
+ '.js-TokenAccess input': 'TokenAccess'
+ '.js-PasswordAccess input': 'PasswordAccess'
+
+ constructor: ->
+ super
+
+ @title 'API', true
+
+ App.Setting.fetchFull(
+ @render
+ force: false
+ )
+
+ render: =>
+
+ # serach area settings
+ settings = App.Setting.search(
+ filter:
+ area: 'API::Base'
+ )
+
+ @html App.view('api')(
+ settings: settings
+ )
+
+ if @subscribeApplicationId
+ App.Setting.unsubscribe(@subscribeApplicationId)
+
+ table = =>
+ new App.ControllerTable(
+ el: @$('.js-appList')
+ model: App.Application
+ table_id: 'applications'
+ objects: App.Application.all()
+ bindRow:
+ events:
+ 'click': @appEdit
+ )
+ table()
+ #App.Application.fetchFull(
+ # table
+ # clear: true
+ #)
+ @subscribeApplicationId = App.Application.subscribe(table, initFetch: true, clear: true)
+
+
+ release: =>
+ super
+ if @subscribeApplicationId
+ App.Application.unsubscribe(@subscribeApplicationId)
+
+ action: (e) ->
+ e.preventDefault()
+ id = $(e.target).parents('[data-id]').data('id')
+ type = $(e.target).data('type')
+ if type is 'uninstall'
+ httpType = 'DELETE'
+
+ if httpType
+ @ajax(
+ id: 'packages'
+ type: httpType
+ url: "#{@apiPath}/packages",
+ data: JSON.stringify(id: id)
+ processData: false
+ success: =>
+ @load()
+ )
+
+ toggleTokenAccess: =>
+ value = @TokenAccess.prop('checked')
+ App.Setting.set('api_token_access', value)
+
+ togglePasswordAccess: =>
+ value = @PasswordAccess.prop('checked')
+ App.Setting.set('api_password_access', value)
+
+ appNew: (e) ->
+ e.preventDefault()
+ new App.ControllerGenericNew(
+ pageData:
+ object: 'Application'
+ genericObject: 'Application'
+ callback: =>
+ @render()
+ container: @el.closest('.content')
+ )
+
+ appEdit: (id, e) =>
+ e.preventDefault()
+ item = App.Application.find(id)
+
+ new App.ControllerGenericEdit(
+ id: item.id
+ pageData:
+ object: 'Application'
+ genericObject: 'Application'
+ callback: =>
+ @render()
+ container: @el.closest('.content')
+ )
+
+App.Config.set('API', { prio: 1200, name: 'API', parent: '#system', target: '#system/api', controller: Index, permission: ['admin.api'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/models/application.coffee b/app/assets/javascripts/app/models/application.coffee
new file mode 100644
index 000000000..85fd37030
--- /dev/null
+++ b/app/assets/javascripts/app/models/application.coffee
@@ -0,0 +1,17 @@
+class App.Application extends App.Model
+ @configure 'Application', 'name', 'scopes', 'redirect_uri'
+ @extend Spine.Model.Ajax
+ @url: @apiPath + '/applications'
+
+ @configure_attributes = [
+ { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
+ { name: 'redirect_uri', display: 'Redirect URI', tag: 'textarea', limit: 250, null: false, note: 'Use one line per URI' },
+ { name: 'scopes', display: 'Scopes', tag: 'input', note: 'Scopes define the access for' },
+ { name: 'clients', display: 'Clients', tag: 'input', readonly: 1 },
+ { name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
+ { name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
+ ]
+ @configure_overview = [
+ 'name', 'scopes', 'clients'
+ ]
+ @configure_delete = true
diff --git a/app/assets/javascripts/app/views/api.jst.eco b/app/assets/javascripts/app/views/api.jst.eco
new file mode 100644
index 000000000..ddffb1fd9
--- /dev/null
+++ b/app/assets/javascripts/app/views/api.jst.eco
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
<%- @T('Enable REST API using tokens (not username/email addeess and password). Each user need to create own access tokens in user profile.') %>
+
+
<%- @T('Example') %>:
+
+
+curl -H "Authorization: Token token=YOUR_TOKEN" <%= @C('http_type') %>://<%= @C('fqdn') %>/api/v1/groups
+
+
+
+
+
+
+
<%- @T('Enable REST API access using the username/email address and password for the authentication user.') %>
+
+
<%- @T('Example') %>:
+
+
+curl -u <%= @S('email') %>:some_password <%= @C('http_type') %>://<%= @C('fqdn') %>/api/v1/groups
+
+
+
+
+
+
+
<%- @T('Manage applications that can use Zammad as an OAuth provider and applications that you\'ve authorized to use your account.') %>
+
+
+
+
+
+
+
+
+OAuth URLs are:
+
+
+
+
+ <%- @T('Title') %>
+ | <%- @T('URL') %>
+ |
+
+
+ <%- @T('Requesting the Grant') %>
+ | <%= @C('http_type') %>://<%= @C('fqdn') %>/oauth/authorize
+ |
+ <%- @T('Getting an Access Token') %>
+ | <%= @C('http_type') %>://<%= @C('fqdn') %>/oauth/token
+ |
+ <%- @T('Revoking Access') %>
+ | <%= @C('http_type') %>://<%= @C('fqdn') %>/oauth/applications
+ |
+
+
+
+
\ No newline at end of file