| /** | |
| * @license | |
| * Copyright (C) 2019 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| import {customElement, property, query, state} from 'lit/decorators.js'; | |
| import {css, CSSResult, html, LitElement} from 'lit'; | |
| import {unsafeHTML} from 'lit/directives/unsafe-html.js'; | |
| import {RestPluginApi} from '@gerritcodereview/typescript-api/rest'; | |
| import { | |
| AccountId, | |
| AccountInfo, | |
| GroupInfo, | |
| } from '@gerritcodereview/typescript-api/rest-api'; | |
| import {PluginApi} from '@gerritcodereview/typescript-api/plugin'; | |
| export interface ConfigInfo { | |
| info: string; | |
| on_success: string; | |
| allow_email: boolean; | |
| allow_owner: boolean; | |
| allow_http_password: boolean; | |
| } | |
| export interface ServiceUserInfo extends AccountInfo { | |
| created_by?: AccountInfo; | |
| created_at?: string; | |
| owner?: GroupInfo; | |
| } | |
| declare interface ServiceUserInput { | |
| username?: string; | |
| name?: string; | |
| ssh_key?: string; | |
| email?: string; | |
| } | |
| @customElement('gr-serviceuser-create') | |
| export class GrServiceUserCreate extends LitElement { | |
| @query('#successDialogModal') | |
| successDialogModal!: HTMLDialogElement; | |
| @query('#serviceUserNameInput') | |
| serviceUserNameInput!: HTMLInputElement; | |
| @query('#serviceUserEmailInput') | |
| serviceUserEmailInput!: HTMLInputElement; | |
| @property() | |
| plugin!: PluginApi; | |
| @property() | |
| pluginRestApi!: RestPluginApi; | |
| @state() | |
| infoMessageEnabled = false; | |
| @state() | |
| successMessageEnabled = false; | |
| @state() | |
| emailAllowed = false; | |
| @state() | |
| dataValid = false; | |
| @state() | |
| isAdding = false; | |
| @property({type: String}) | |
| infoMessage = ''; | |
| @property({type: String}) | |
| successMessage = ''; | |
| @property({type: String}) | |
| username?: String; | |
| @property({type: String}) | |
| email?: String; | |
| @property({type: Object}) | |
| accountId?: AccountId; | |
| static override get styles() { | |
| return [ | |
| window.Gerrit.styles.font as CSSResult, | |
| window.Gerrit.styles.form as CSSResult, | |
| window.Gerrit.styles.modal as CSSResult, | |
| window.Gerrit.styles.subPage as CSSResult, | |
| css` | |
| main { | |
| margin: 2em auto; | |
| max-width: 50em; | |
| } | |
| .heading { | |
| font-size: x-large; | |
| font-weight: 500; | |
| } | |
| `, | |
| ]; | |
| } | |
| override render() { | |
| return html` | |
| <main class="gr-form-styles read-only"> | |
| <div class="topHeader"> | |
| <h1 class="heading">Create Service User</h1> | |
| </div> | |
| ${this.renderInfoMessage()} | |
| <fieldset> | |
| <section> | |
| <span class="title">Username</span> | |
| <span class="value"> | |
| <input | |
| id="serviceUserNameInput" | |
| value="${this.username}" | |
| type="text" | |
| @input="${this.validateData}" | |
| /> | |
| </span> | |
| </section> | |
| ${this.renderEmailInputSection()} | |
| </fieldset> | |
| <gr-button | |
| id="createButton" | |
| @click=${this.handleCreateServiceUser} | |
| ?disabled="${!this.dataValid || this.isAdding}" | |
| > | |
| Create | |
| </gr-button> | |
| <dialog id="successDialogModal"> | |
| <gr-dialog | |
| id="successDialog" | |
| confirm-label="OK" | |
| cancel-label="" | |
| @confirm="${this.forwardToDetails}" | |
| confirm-on-enter | |
| > | |
| <div slot="header">Success</div> | |
| <div id="successMessage" slot="main"> | |
| ${this.renderSuccessMessage()} | |
| </div> | |
| </gr-dialog> | |
| </dialog> | |
| </main> | |
| `; | |
| } | |
| private renderSuccessMessage() { | |
| return html`${unsafeHTML(this.successMessage)}`; | |
| } | |
| private renderInfoMessage() { | |
| if (this.infoMessageEnabled) { | |
| return html` | |
| <fieldset id="infoMessage">${unsafeHTML(this.infoMessage)}</fieldset> | |
| `; | |
| } | |
| return html``; | |
| } | |
| private renderEmailInputSection() { | |
| if (this.emailAllowed) { | |
| return html` | |
| <section> | |
| <span class="title">Email</span> | |
| <span class="value"> | |
| <input | |
| id="serviceUserEmailInput" | |
| value="${this.email}" | |
| type="text" | |
| @input="${this.validateData}" | |
| /> | |
| </span> | |
| </section> | |
| `; | |
| } | |
| return html``; | |
| } | |
| override connectedCallback() { | |
| super.connectedCallback(); | |
| this.pluginRestApi = this.plugin.restApi(); | |
| this.getConfig(); | |
| } | |
| private forwardToDetails() { | |
| window.location.href = `${this.getPluginBaseURL()}/user/${this.accountId}`; | |
| } | |
| private getPluginBaseURL() { | |
| return `${window.location.origin}${window.CANONICAL_PATH || ''}/x/${this.plugin.getPluginName()}`; | |
| } | |
| private getConfig() { | |
| return this.pluginRestApi | |
| .get<ConfigInfo>('/config/server/serviceuser~config/') | |
| .then(config => { | |
| if (!config) { | |
| return; | |
| } | |
| if (config.info && config.info !== '') { | |
| this.infoMessageEnabled = true; | |
| this.infoMessage = config.info; | |
| } | |
| if (config.on_success && config.on_success !== '') { | |
| this.successMessageEnabled = true; | |
| this.successMessage = config.on_success; | |
| } | |
| this.emailAllowed = config.allow_email; | |
| }); | |
| } | |
| private validateData() { | |
| this.dataValid = | |
| this.validateName(this.serviceUserNameInput.value) && | |
| this.validateEmail(this.serviceUserEmailInput?.value); | |
| } | |
| private validateName(username: String | undefined) { | |
| if (username && username.trim().length > 0) { | |
| this.username = username; | |
| return true; | |
| } | |
| return false; | |
| } | |
| private validateEmail(email: String | undefined) { | |
| if (!email || email.trim().length === 0 || email.includes('@')) { | |
| this.email = email; | |
| return true; | |
| } | |
| return false; | |
| } | |
| private handleCreateServiceUser() { | |
| this.isAdding = true; | |
| const body: ServiceUserInput = { | |
| email: this.email ? this.email.trim() : '', | |
| }; | |
| return this.plugin | |
| .restApi() | |
| .post<ServiceUserInfo>( | |
| `/a/config/server/serviceuser~serviceusers/${this.username}`, | |
| body | |
| ) | |
| .then(response => { | |
| this.accountId = response._account_id; | |
| if (this.successMessage) { | |
| this.successDialogModal?.showModal(); | |
| } else { | |
| this.forwardToDetails(); | |
| } | |
| }) | |
| .catch(response => { | |
| this.dispatchEvent( | |
| new CustomEvent('show-error', { | |
| detail: {message: response}, | |
| bubbles: true, | |
| composed: true, | |
| }) | |
| ); | |
| this.isAdding = false; | |
| }); | |
| } | |
| } |