"use strict";(self.webpackChunkgrafana=self.webpackChunkgrafana||[]).push([[3082],{60277:(L,K,n)=>{n.r(K),n.d(K,{ApiKeysPageUnconnected:()=>F,default:()=>Fe});var e=n(68404),B=n(36635),N=n(33180),$=n(37932),M=n(52081),T=n(81764),z=n(8944),H=n(97063),Q=n(69142),x=n(79396),V=n(47694),b=n(77582),Y=n(25405),h=n(81168),Z=n(45984),c=n(52423),I=n(72648),P=n(45253),v=n(31403),w=n(98102);const U=({onHideApiKeys:t})=>{const[a,s]=(0,e.useState)(!1),o=(0,I.wW)(W);return e.createElement(P.b,{title:"API keys were migrated to Grafana service accounts. This tab is deprecated.",severity:"info"},e.createElement("div",{className:o.text},"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."),e.createElement("div",{className:o.actionRow},e.createElement(v.zx,{className:o.actionButton,onClick:()=>s(!0)},"Hide API keys page forever"),e.createElement(w.s,{title:"Hide API Keys page forever",isOpen:a,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:t,onDismiss:()=>s(!1)}),e.createElement("a",{href:"org/serviceaccounts"},"View service accounts page")))},W=t=>({text:c.css`
    margin-bottom: ${t.spacing(2)};
  `,actionRow:c.css`
    display: flex;
    align-items: center;
  `,actionButton:c.css`
    margin-right: ${t.spacing(2)};
  `});var G=n(14747);const j=({searchQuery:t,disabled:a,onAddClick:s,onSearchChange:o})=>e.createElement("div",{className:"page-action-bar"},e.createElement("div",{className:"gf-form gf-form--grow"},e.createElement(G.H,{placeholder:"Search keys",value:t,onChange:o})),e.createElement(v.zx,{className:"pull-right",onClick:s,disabled:a},"Add API key"));var J=n(35029),X=n(24799),q=n(46967),_=n(94599);function ee({onDismiss:t,apiKey:a,rootPath:s}){const o=(0,I.wW)(te),r=(0,e.useCallback)(()=>a,[a]);return e.createElement(J.u,{title:"API Key Created",onDismiss:t,onClickBackdrop:t,isOpen:!0},e.createElement(X.g,{label:"Key"},e.createElement(q.I,{id:"Key",value:a,readOnly:!0,addonAfter:e.createElement(_.m,{icon:"copy",variant:"primary",getText:r},"Copy")})),e.createElement(P.b,{severity:"info",title:"You will only be able to view this key here once!"},"It is not stored in this form, so be sure to copy it now."),e.createElement("p",{className:"text-muted"},"You can authenticate a request using the Authorization HTTP header, example:"),e.createElement("pre",{className:o.small},'curl -H "Authorization: Bearer ',a,'" ',s,"/api/dashboards/home"))}function te(t){return{label:c.css`
      padding: ${t.spacing(1)};
      background-color: ${t.colors.background.secondary};
      border-radius: ${t.shape.borderRadius()};
    `,small:c.css`
      font-size: ${t.typography.bodySmall.fontSize};
      font-weight: ${t.typography.bodySmall.fontWeight};
    `}}const ne=({children:t})=>{const[a,s]=(0,e.useState)(!1),o=(0,e.useCallback)(()=>{s(!a)},[a]);return t({isAdding:a,toggleIsAdding:o})};var ae=n(14835),se=n(59481),oe=n(53217),ie=n(50796),re=n(1108);const{Input:k}=ae.LegacyForms,le=Object.keys(h.OrgRole).map(t=>({label:t,value:t}));function D(t){if(!t)return!0;try{return N.intervalToSeconds(t),!0}catch{}return!1}const ce={[se.JU.onBlur]:[{rule:D,errorMessage:"Not a valid duration"}]},de="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",me=({show:t,onClose:a,onKeyAdded:s,disabled:o})=>{const[r,l]=(0,e.useState)(""),[i,d]=(0,e.useState)(h.OrgRole.Viewer),[u,g]=(0,e.useState)("");(0,e.useEffect)(()=>{l(""),d(h.OrgRole.Viewer),g("")},[t]);const f=p=>{p.preventDefault(),D(u)&&(s({name:r,role:i,secondsToLive:u}),a())},A=p=>{l(p.currentTarget.value)},S=p=>{d(p.value)},C=p=>{g(p.currentTarget.value)};return e.createElement(re.s,{in:t},e.createElement("div",{className:"gf-form-inline cta-form"},e.createElement(ie.P,{onClick:a}),e.createElement("form",{className:"gf-form-group",onSubmit:f},e.createElement("h5",null,"Add API Key"),e.createElement("div",{className:"gf-form-inline"},e.createElement("div",{className:"gf-form max-width-21"},e.createElement("span",{className:"gf-form-label"},"Key name"),e.createElement(k,{type:"text",className:"gf-form-input",value:r,placeholder:"Name",onChange:A})),e.createElement("div",{className:"gf-form"},e.createElement(T._,{label:"Role"},e.createElement(oe.Ph,{inputId:"role-select",value:i,onChange:S,options:le}))),e.createElement("div",{className:"gf-form max-width-21"},e.createElement(T._,{tooltip:de,label:"Time to live"},e.createElement(k,{id:"time-to-live-input",type:"text",placeholder:"1d",validationEvents:ce,value:u,onChange:C}))),e.createElement("div",{className:"gf-form"},e.createElement(v.zx,{type:"submit",disabled:o},"Add"))))))};var ue=n(38849),pe=n(61860),ye=n(39904),ge=n(13626);const he=({apiKeys:t,timeZone:a,onDelete:s,onMigrate:o})=>{const r=(0,I.l4)(),l=Ee(r);return e.createElement("table",{className:"filter-table"},e.createElement("thead",null,e.createElement("tr",null,e.createElement("th",null,"Name"),e.createElement("th",null,"Role"),e.createElement("th",null,"Expires"),e.createElement("th",{style:{width:"34px"}}))),t.length>0?e.createElement("tbody",null,t.map(i=>{const d=Boolean(i.expiration&&Date.now()>new Date(i.expiration).getTime());return e.createElement("tr",{key:i.id,className:l.tableRow(d)},e.createElement("td",null,i.name),e.createElement("td",null,i.role),e.createElement("td",null,ve(i.expiration,a),d&&e.createElement("span",{className:l.tooltipContainer},e.createElement(pe.u,{content:"This API key has expired."},e.createElement(ye.J,{name:"exclamation-triangle"})))),e.createElement("td",null,e.createElement(M.Lh,{justify:"flex-end"},e.createElement(v.zx,{size:"sm",onClick:()=>o(i)},"Migrate to service account"),e.createElement(ge.m,{"aria-label":"Delete API key",size:"sm",onConfirm:()=>s(i),disabled:!b.Vt.hasPermissionInMetadata(h.AccessControlAction.ActionAPIKeysDelete,i)}))))})):null)};function ve(t,a){return t?(0,ue.dq)(t,{timeZone:a}):"No expiration date"}const Ee=t=>({tableRow:a=>c.css`
    color: ${a?t.colors.text.secondary:t.colors.text.primary};
  `,tooltipContainer:c.css`
    margin-left: ${t.spacing(1)};
  `}),fe=({onMigrate:t,disabled:a})=>{const[s,o]=(0,e.useState)(!1),r=(0,I.wW)(Ae),l=e.createElement("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"},"here."),i=e.createElement("span",null,"Are you sure you want to migrate all API keys to service accounts? Find out more ",l);return e.createElement(P.b,{title:"Switch from API keys to service accounts",severity:"info"},e.createElement("div",{className:r.text},"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."),e.createElement("div",{className:r.actionRow},e.createElement(v.zx,{className:r.actionButton,onClick:()=>o(!0)},"Migrate to service accounts now"),e.createElement(w.s,{title:"Migrate API keys to service accounts",isOpen:s,body:i,confirmText:"Yes, migrate now",onConfirm:t,onDismiss:()=>o(!1)})))},Ae=t=>({text:c.css`
    margin-bottom: ${t.spacing(2)};
  `,actionRow:c.css`
    display: flex;
    align-items: center;
  `,actionButton:c.css`
    margin-right: ${t.spacing(2)};
  `});var m=n(29930),Ke=n(58379),xe=n(75127),y=n(56777);function Ie(t,a){return async s=>{const o=await(0,m.i)().post("/api/auth/keys",t);s((0,y.ql)("")),s(E()),a(o.key)}}function E(){return async t=>{t((0,y.dF)());const[a,s]=await Promise.all([(0,m.i)().get("/api/auth/keys?includeExpired=false&accesscontrol=true"),(0,m.i)().get("/api/auth/keys?includeExpired=true&accesscontrol=true")]);t((0,y.iK)({keys:a,keysIncludingExpired:s}))}}function Ce(t){return async a=>{(0,m.i)().delete(`/api/auth/keys/${t}`).then(()=>a(E()))}}function Te(t){return async a=>{try{await(0,m.i)().post(`/api/serviceaccounts/migrate/${t}`)}finally{a(E())}}}function Pe(){return async t=>{try{await(0,m.i)().post("/api/serviceaccounts/migrate"),Ke.Z.set(xe.t,!0)}finally{t(R()),t(E())}}}function R(){return async t=>{const a=await(0,m.i)().get("/api/serviceaccounts/migrationstatus");t((0,y.cB)(!!a?.migrated))}}function Se(){return async t=>{await(0,m.i)().post("/api/serviceaccounts/hideApiKeys")}}function Ne(){return t=>{t((0,y.j4)())}}const Me=t=>t.includeExpired?t.keysIncludingExpired.length:t.keys.length,be=t=>{const a=RegExp(t.searchQuery,"i");return(t.includeExpired?t.keysIncludingExpired:t.keys).filter(o=>a.test(o.name)||a.test(o.role))},we=t=>t.includeExpired,ke=t=>t.keys.length===0&&t.keysIncludingExpired.length>0;function De(t){const a=b.Vt.hasAccess(h.AccessControlAction.ActionAPIKeysCreate,!0);return{apiKeys:be(t.apiKeys),searchQuery:t.apiKeys.searchQuery,apiKeysCount:Me(t.apiKeys),hasFetched:t.apiKeys.hasFetched,timeZone:(0,Y.Z)(t.user),includeExpired:we(t.apiKeys),includeExpiredDisabled:ke(t.apiKeys),canCreate:a,apiKeysMigrated:t.apiKeys.apiKeysMigrated}}const O={navId:"apikeys"},Re={loadApiKeys:E,deleteApiKey:Ce,migrateApiKey:Te,migrateAll:Pe,setSearchQuery:y.ql,toggleIncludeExpired:Ne,addApiKey:Ie,getApiKeysMigrationStatus:R,hideApiKeys:Se},Oe=(0,B.connect)(De,Re);class F extends e.PureComponent{constructor(a){super(a),this.onDeleteApiKey=s=>{this.props.deleteApiKey(s.id)},this.onMigrateAll=()=>{this.props.migrateAll()},this.onMigrateApiKey=s=>{this.props.migrateApiKey(s.id)},this.onSearchQueryChange=s=>{this.props.setSearchQuery(s)},this.onIncludeExpiredChange=s=>{this.props.toggleIncludeExpired()},this.onAddApiKey=s=>{const o=l=>{const i=window.location.origin+V.ZP.appSubUrl;H.Z.publish(new Z.Dn({props:{apiKey:l,rootPath:i},component:ee}))},r=s.secondsToLive;try{const l=r?N.intervalToSeconds(r):null,i={...s,secondsToLive:l};this.props.addApiKey(i,o),this.setState(d=>({...d,isAdding:!1}))}catch(l){console.error(l)}},this.onHideApiKeys=async()=>{try{await this.props.hideApiKeys();let s="/org/serviceaccounts";$.E1.push(s),window.location.reload()}catch(s){console.error(s)}}}componentDidMount(){this.fetchApiKeys(),this.props.getApiKeysMigrationStatus()}async fetchApiKeys(){await this.props.loadApiKeys()}render(){const{hasFetched:a,apiKeysCount:s,apiKeys:o,searchQuery:r,timeZone:l,includeExpired:i,includeExpiredDisabled:d,canCreate:u,apiKeysMigrated:g}=this.props;return a?e.createElement(x.T,{...O},e.createElement(x.T.Contents,{isLoading:!1},e.createElement(ne,null,({isAdding:f,toggleIsAdding:A})=>{const S=!f&&s===0&&!g,C=s>0;return e.createElement(e.Fragment,null,!g&&e.createElement(fe,{onMigrate:this.onMigrateAll}),g&&e.createElement(U,{onHideApiKeys:this.onHideApiKeys}),S?e.createElement(Q.Z,{title:"You haven't added any API keys yet.",buttonIcon:"key-skeleton-alt",onClick:A,buttonTitle:"New API key",proTip:"Remember, you can provide view-only API access to other applications.",buttonDisabled:!u}):null,C?e.createElement(j,{searchQuery:r,disabled:f||!u,onAddClick:A,onSearchChange:this.onSearchQueryChange}):null,e.createElement(me,{show:f,onClose:A,onKeyAdded:this.onAddApiKey,disabled:!u}),C?e.createElement(M.wc,null,e.createElement(T._,{disabled:d,label:"Include expired keys"},e.createElement(z.x,{id:"showExpired",value:i,onChange:this.onIncludeExpiredChange})),e.createElement(he,{apiKeys:o,timeZone:l,onMigrate:this.onMigrateApiKey,onDelete:this.onDeleteApiKey})):null)}))):e.createElement(x.T,{...O},e.createElement(x.T.Contents,{isLoading:!0}))}}const Fe=Oe(F)},75127:(L,K,n)=>{n.d(K,{t:()=>e});const e="grafana.serviceaccounts.showApiKeysMigrationInfo"}}]);

//# sourceMappingURL=ApiKeysPage.57cb5868e864c7bc24e9.js.map