"use strict";(self.webpackChunkgrafana=self.webpackChunkgrafana||[]).push([[3082],{10106:(e,s,i)=>{i.r(s),i.d(s,{ApiKeysPageUnconnected:()=>we,default:()=>Ke});var t,n=i(68404),a=i(1485),r=i(23541),o=i(98712),c=i(25049),l=i(24643),d=i(72786),h=i(5831),u=i(28436),p=i(90894),y=i(78837),g=i(98163),x=i(78647),m=i(47570),f=i(21169),j=i(27549),A=i(9617),v=i(8771),b=i(40920),k=i(95378),w=i(45916);const K=e=>{let{onHideApiKeys:s}=e;const[i,a]=(0,n.useState)(!1),r=(0,A.wW)(I);return(0,w.jsxs)(v.b,{title:"API keys were migrated to Grafana service accounts. This tab is deprecated.",severity:"info",children:[(0,w.jsx)("div",{className:r.text,children:"We have migrated API keys into Grafana service accounts. All API keys are safe and continue working as they used to, you can find them inside the respective service account."}),(0,w.jsxs)("div",{className:r.actionRow,children:[(0,w.jsx)(b.zx,{className:r.actionButton,onClick:()=>a(!0),children:"Hide API keys page forever"}),(0,w.jsx)(k.s,{title:"Hide API Keys page forever",isOpen:i,body:"Are you sure you want to hide API keys page forever and use service accounts from now on?",confirmText:"Yes, hide API keys page.",onConfirm:s,onDismiss:()=>a(!1)}),t||(t=(0,w.jsx)("a",{href:"org/serviceaccounts",children:"View service accounts page"}))]})]})},I=e=>({text:j.css`
    margin-bottom: ${e.spacing(2)};
  `,actionRow:j.css`
    display: flex;
    align-items: center;
  `,actionButton:j.css`
    margin-right: ${e.spacing(2)};
  `});var C=i(74819);const P=e=>{let{searchQuery:s,disabled:i,onAddClick:t,onSearchChange:n}=e;return(0,w.jsxs)("div",{className:"page-action-bar",children:[(0,w.jsx)("div",{className:"gf-form gf-form--grow",children:(0,w.jsx)(C.H,{placeholder:"Search keys",value:s,onChange:n})}),(0,w.jsx)(b.zx,{className:"pull-right",onClick:t,disabled:i,children:"Add API key"})]})};var N,S,E=i(59385),T=i(84719),M=i(1652),D=i(18625);function $(e){let{onDismiss:s,apiKey:i,rootPath:t}=e;const a=(0,A.wW)(B),r=(0,n.useCallback)((()=>i),[i]);return(0,w.jsxs)(E.u,{title:"API Key Created",onDismiss:s,onClickBackdrop:s,isOpen:!0,children:[(0,w.jsx)(T.g,{label:"Key",children:(0,w.jsx)(M.I,{id:"Key",value:i,readOnly:!0,addonAfter:(0,w.jsx)(D.m,{icon:"copy",variant:"primary",getText:r,children:"Copy"})})}),N||(N=(0,w.jsx)(v.b,{severity:"info",title:"You will only be able to view this key here once!",children:"It is not stored in this form, so be sure to copy it now."})),S||(S=(0,w.jsx)("p",{className:"text-muted",children:"You can authenticate a request using the Authorization HTTP header, example:"})),(0,w.jsxs)("pre",{className:a.small,children:['curl -H "Authorization: Bearer ',i,'" ',t,"/api/dashboards/home"]})]})}function B(e){return{label:j.css`
      padding: ${e.spacing(1)};
      background-color: ${e.colors.background.secondary};
      border-radius: ${e.shape.borderRadius()};
    `,small:j.css`
      font-size: ${e.typography.bodySmall.fontSize};
      font-weight: ${e.typography.bodySmall.fontWeight};
    `}}const z=e=>{let{children:s}=e;const[i,t]=(0,n.useState)(!1),a=(0,n.useCallback)((()=>{t(!i)}),[i]);return s({isAdding:i,toggleIsAdding:a})};var R,O,Q=i(59912),Z=i(91838),H=i(2563),F=i(6347),W=i(72779);const{Input:L}=Q.vw6,V=Object.keys(m.B5).map((e=>({label:e,value:e})));function Y(e){if(!e)return!0;try{return r.intervalToSeconds(e),!0}catch{}return!1}const q={[Z.JU.onBlur]:[{rule:Y,errorMessage:"Not a valid duration"}]},_=e=>{let{show:s,onClose:i,onKeyAdded:t,disabled:a}=e;const[r,o]=(0,n.useState)(""),[c,d]=(0,n.useState)(m.B5.Viewer),[h,u]=(0,n.useState)("");(0,n.useEffect)((()=>{o(""),d(m.B5.Viewer),u("")}),[s]);return(0,w.jsx)(W.s,{in:s,children:(0,w.jsxs)("div",{className:"gf-form-inline cta-form",children:[(0,w.jsx)(F.P,{onClick:i}),(0,w.jsxs)("form",{className:"gf-form-group",onSubmit:e=>{e.preventDefault(),Y(h)&&(t({name:r,role:c,secondsToLive:h}),i())},children:[R||(R=(0,w.jsx)("h5",{children:"Add API Key"})),(0,w.jsxs)("div",{className:"gf-form-inline",children:[(0,w.jsxs)("div",{className:"gf-form max-width-21",children:[O||(O=(0,w.jsx)("span",{className:"gf-form-label",children:"Key name"})),(0,w.jsx)(L,{type:"text",className:"gf-form-input",value:r,placeholder:"Name",onChange:e=>{o(e.currentTarget.value)}})]}),(0,w.jsx)("div",{className:"gf-form",children:(0,w.jsx)(l._,{label:"Role",children:(0,w.jsx)(H.Ph,{inputId:"role-select",value:c,onChange:e=>{d(e.value)},options:V})})}),(0,w.jsx)("div",{className:"gf-form max-width-21",children:(0,w.jsx)(l._,{tooltip:"The API key life duration. For example, 1d if your key is going to last for one day. Supported units are: s,m,h,d,w,M,y",label:"Time to live",children:(0,w.jsx)(L,{id:"time-to-live-input",type:"text",placeholder:"1d",validationEvents:q,value:h,onChange:e=>{u(e.currentTarget.value)}})})}),(0,w.jsx)("div",{className:"gf-form",children:(0,w.jsx)(b.zx,{type:"submit",disabled:a,children:"Add"})})]})]})]})})};var U,G,J,X,ee=i(27494),se=i(9442),ie=i(24085),te=i(78146);const ne=e=>{let{apiKeys:s,timeZone:i,onDelete:t,onMigrate:n}=e;const a=(0,A.l4)(),r=re(a);return(0,w.jsxs)("table",{className:"filter-table",children:[(0,w.jsx)("thead",{children:(0,w.jsxs)("tr",{children:[U||(U=(0,w.jsx)("th",{children:"Name"})),G||(G=(0,w.jsx)("th",{children:"Role"})),J||(J=(0,w.jsx)("th",{children:"Expires"})),(0,w.jsx)("th",{style:{width:"34px"}})]})}),s.length>0?(0,w.jsx)("tbody",{children:s.map((e=>{const s=Boolean(e.expiration&&Date.now()>new Date(e.expiration).getTime());return(0,w.jsxs)("tr",{className:r.tableRow(s),children:[(0,w.jsx)("td",{children:e.name}),(0,w.jsx)("td",{children:e.role}),(0,w.jsxs)("td",{children:[ae(e.expiration,i),s&&(0,w.jsx)("span",{className:r.tooltipContainer,children:X||(X=(0,w.jsx)(se.u,{content:"This API key has expired.",children:(0,w.jsx)(ie.J,{name:"exclamation-triangle"})}))})]}),(0,w.jsx)("td",{children:(0,w.jsxs)(c.Lh,{justify:"flex-end",children:[(0,w.jsx)(b.zx,{size:"sm",onClick:()=>n(e),children:"Migrate to service account"}),(0,w.jsx)(te.m,{"aria-label":"Delete API key",size:"sm",onConfirm:()=>t(e),disabled:!g.Vt.hasPermissionInMetadata(m.bW.ActionAPIKeysDelete,e)})]})})]},e.id)}))}):null]})};function ae(e,s){return e?(0,ee.dq)(e,{timeZone:s}):"No expiration date"}const re=e=>({tableRow:s=>j.css`
    color: ${s?e.colors.text.secondary:e.colors.text.primary};
  `,tooltipContainer:j.css`
    margin-left: ${e.spacing(1)};
  `});var oe;const ce=e=>{let{onMigrate:s,disabled:i}=e;const[t,a]=(0,n.useState)(!1),r=(0,A.wW)(le),o=oe||(oe=(0,w.jsx)("a",{className:"external-link",href:"https://grafana.com/docs/grafana/latest/administration/api-keys/#migrate-api-keys-to-grafana-service-accounts/",target:"_blank",rel:"noopener noreferrer",children:"here."})),c=(0,w.jsxs)("span",{children:["Are you sure you want to migrate all API keys to service accounts? Find out more ",o]});return(0,w.jsxs)(v.b,{title:"Switch from API keys to service accounts",severity:"info",children:[(0,w.jsx)("div",{className:r.text,children:"Each API key will be automatically migrated into a service account with a token. The service account will be created with the same permission as the API Key and current API Keys will continue to work as they were."}),(0,w.jsxs)("div",{className:r.actionRow,children:[(0,w.jsx)(b.zx,{className:r.actionButton,onClick:()=>a(!0),children:"Migrate to service accounts now"}),(0,w.jsx)(k.s,{title:"Migrate API keys to service accounts",isOpen:t,body:c,confirmText:"Yes, migrate now",onConfirm:s,onDismiss:()=>a(!1)})]})]})},le=e=>({text:j.css`
    margin-bottom: ${e.spacing(2)};
  `,actionRow:j.css`
    display: flex;
    align-items: center;
  `,actionButton:j.css`
    margin-right: ${e.spacing(2)};
  `});var de=i(28659),he=i(17421),ue=i(89847),pe=i(88467);function ye(){return async e=>{e((0,pe.dF)());const[s,i]=await Promise.all([(0,de.i)().get("/api/auth/keys?includeExpired=false&accesscontrol=true"),(0,de.i)().get("/api/auth/keys?includeExpired=true&accesscontrol=true")]);e((0,pe.iK)({keys:s,keysIncludingExpired:i}))}}function ge(){return async e=>{const s=await(0,de.i)().get("/api/serviceaccounts/migrationstatus");e((0,pe.cB)(!(null==s||!s.migrated)))}}const xe=e=>e.includeExpired?e.keysIncludingExpired.length:e.keys.length,me=e=>{const s=RegExp(e.searchQuery,"i");return(e.includeExpired?e.keysIncludingExpired:e.keys).filter((e=>s.test(e.name)||s.test(e.role)))},fe=e=>e.includeExpired,je=e=>0===e.keys.length&&e.keysIncludingExpired.length>0;function Ae(e,s,i){return s in e?Object.defineProperty(e,s,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[s]=i,e}const ve={navId:"apikeys"},be={loadApiKeys:ye,deleteApiKey:function(e){return async s=>{(0,de.i)().delete(`/api/auth/keys/${e}`).then((()=>s(ye())))}},migrateApiKey:function(e){return async s=>{try{await(0,de.i)().post(`/api/serviceaccounts/migrate/${e}`)}finally{s(ye())}}},migrateAll:function(){return async e=>{try{await(0,de.i)().post("/api/serviceaccounts/migrate"),he.Z.set(ue.t,!0)}finally{e(ge()),e(ye())}}},setSearchQuery:pe.ql,toggleIncludeExpired:function(){return e=>{e((0,pe.j4)())}},addApiKey:function(e,s){return async i=>{const t=await(0,de.i)().post("/api/auth/keys",e);i((0,pe.ql)("")),i(ye()),s(t.key)}},getApiKeysMigrationStatus:ge,hideApiKeys:function(){return async e=>{await(0,de.i)().post("/api/serviceaccounts/hideApiKeys")}}},ke=(0,a.connect)((function(e){const s=g.Vt.hasAccess(m.bW.ActionAPIKeysCreate,!0);return{apiKeys:me(e.apiKeys),searchQuery:e.apiKeys.searchQuery,apiKeysCount:xe(e.apiKeys),hasFetched:e.apiKeys.hasFetched,timeZone:(0,x.Z)(e.user),includeExpired:fe(e.apiKeys),includeExpiredDisabled:je(e.apiKeys),canCreate:s,apiKeysMigrated:e.apiKeys.apiKeysMigrated}}),be);class we extends n.PureComponent{constructor(e){super(e),Ae(this,"onDeleteApiKey",(e=>{this.props.deleteApiKey(e.id)})),Ae(this,"onMigrateAll",(()=>{this.props.migrateAll()})),Ae(this,"onMigrateApiKey",(e=>{this.props.migrateApiKey(e.id)})),Ae(this,"onSearchQueryChange",(e=>{this.props.setSearchQuery(e)})),Ae(this,"onIncludeExpiredChange",(e=>{this.props.toggleIncludeExpired()})),Ae(this,"onAddApiKey",(e=>{const s=e=>{const s=window.location.origin+y.ZP.appSubUrl;h.Z.publish(new f.Dn({props:{apiKey:e,rootPath:s},component:$}))},i=e.secondsToLive;try{const t=i?r.intervalToSeconds(i):null,n=Object.assign({},e,{secondsToLive:t});this.props.addApiKey(n,s),this.setState((e=>Object.assign({},e,{isAdding:!1})))}catch(e){console.error(e)}})),Ae(this,"onHideApiKeys",(async()=>{try{await this.props.hideApiKeys();let e="/org/serviceaccounts";o.E1.push(e),window.location.reload()}catch(e){console.error(e)}}))}componentDidMount(){this.fetchApiKeys(),this.props.getApiKeysMigrationStatus()}async fetchApiKeys(){await this.props.loadApiKeys()}render(){const{hasFetched:e,apiKeysCount:s,apiKeys:i,searchQuery:t,timeZone:n,includeExpired:a,includeExpiredDisabled:r,canCreate:o,apiKeysMigrated:h}=this.props;return e?(0,w.jsx)(p.T,Object.assign({},ve,{children:(0,w.jsx)(p.T.Contents,{isLoading:!1,children:(0,w.jsx)(z,{children:e=>{let{isAdding:p,toggleIsAdding:y}=e;const g=!p&&0===s&&!h,x=s>0;return(0,w.jsxs)(w.Fragment,{children:[!h&&(0,w.jsx)(ce,{onMigrate:this.onMigrateAll}),h&&(0,w.jsx)(K,{onHideApiKeys:this.onHideApiKeys}),g?(0,w.jsx)(u.Z,{title:"You haven't added any API keys yet.",buttonIcon:"key-skeleton-alt",onClick:y,buttonTitle:"New API key",proTip:"Remember, you can provide view-only API access to other applications.",buttonDisabled:!o}):null,x?(0,w.jsx)(P,{searchQuery:t,disabled:p||!o,onAddClick:y,onSearchChange:this.onSearchQueryChange}):null,(0,w.jsx)(_,{show:p,onClose:y,onKeyAdded:this.onAddApiKey,disabled:!o}),x?(0,w.jsxs)(c.wc,{children:[(0,w.jsx)(l._,{disabled:r,label:"Include expired keys",children:(0,w.jsx)(d.x,{id:"showExpired",value:a,onChange:this.onIncludeExpiredChange})}),(0,w.jsx)(ne,{apiKeys:i,timeZone:n,onMigrate:this.onMigrateApiKey,onDelete:this.onDeleteApiKey})]}):null]})}})})})):(0,w.jsx)(p.T,Object.assign({},ve,{children:(0,w.jsx)(p.T.Contents,{isLoading:!0})}))}}const Ke=ke(we)}}]);
//# sourceMappingURL=ApiKeysPage.2f4b3e145ca28d523f8e.js.map