blob: 6e548b213a83608bb1b6252af659a8cbd1676ee7 [file] [log] [blame]
<template>
<div>
<div class="row">
<div class="col">
<h1 class="h4 mb-4 heading"> Tenant Wizard</h1>
</div>
</div>
<b-form @submit="onSubmit">
<div class="h-tabs card" align="left">
<div class="h-tab">
<!-- <div align="center" v-on:click="onClickHandler(1)" v-bind:class="[tabIndex===1 ? 'tab-content-active' : 'tab-content' ]">Requester Info</div>-->
<div align="center" v-on:click="onClickHandler(1)"
v-bind:class="[tabIndex===1 ? 'tab-content-active' : 'tab-content' ]">Gateway Admin details
</div>
<div align="center" v-on:click="onClickHandler(2)"
v-bind:class="[tabIndex===2 ? 'tab-content-active' : 'tab-content' ]">Gateway details
</div>
<div align="center" v-on:click="onClickHandler(3)"
v-bind:class="[tabIndex===3 ? 'tab-content-active' : 'tab-content' ]">Tenant Credentials
</div>
</div>
<div v-if="tabIndex === 1" class="content">
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
description=""
id="fieldset-1"
label="Admin Username"
label-for="admin-username"
class="inputLabels"
>
<b-form-input
:state="!$v.form.tab1.admin_username.$invalid"
id="admin-username"
name="admin-username"
trim
v-model="form.tab1.admin_username"
readonly>
</b-form-input>
</b-form-group>
<b-form-row>
<b-col>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
description=""
id="fieldset-4"
label="Admin First Name"
label-for="admin-first-name"
class="inputLabels"
>
<b-form-input
:state="!$v.form.tab1.admin_first_name.$invalid"
id="admin-first-name"
name="admin-first-name"
trim
v-model="form.tab1.admin_first_name">
</b-form-input>
</b-form-group>
</b-col>
<b-col>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
description=""
id="fieldset-5"
label="Admin Last Name"
label-for="admin-last-name"
class="inputLabels"
>
<b-form-input
:state="!$v.form.tab1.admin_last_name.$invalid"
id="admin-last-name"
name="admin-last-name"
trim
v-model="form.tab1.admin_last_name">
</b-form-input>
</b-form-group>
</b-col>
</b-form-row>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
description=""
id="fieldset-6"
label="Admin Email"
label-for="admin-email"
class="inputLabels"
>
<b-form-input
:state="!$v.form.tab1.admin_email.$invalid"
id="admin-email"
name="admin-email"
trim
type="email"
v-model="form.tab1.admin_email"
readonly
>
</b-form-input>
</b-form-group>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
description=""
id="fieldset-7"
label="Admin Password"
label-for="admin-password"
class="inputLabels"
>
<b-input :state="!$v.form.tab1.admin_password.$invalid"
aria-describedby="password-help-block"
id="admin-password"
name="admin-password"
trim
type="password"
v-model="form.tab1.admin_password"></b-input>
<b-form-text id="password-help-block">
Your password must be at least 8 characters long, and must contain letters and
numbers, and must at least one special character.
</b-form-text>
</b-form-group>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
description=""
id="fieldset-8"
label="Confirm Admin Password"
label-for="confirm-admin-password"
class="inputLabels"
>
<b-input :state="!$v.form.tab1.confirm_admin_password.$invalid"
aria-describedby="password-help-block"
id="confirm-admin-password"
name="confirm-admin-password"
trim
type="password"
v-model="form.tab1.confirm_admin_password"></b-input>
</b-form-group>
</div>
<div v-if="tabIndex === 2" class="content">
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
id="fieldset-9"
description="The Client Name is displayed to end-users on the Identity Provider selection page."
label="Tenant Name"
label-for="client-name"
class="inputLabels"
>
<b-form-input
:state="!$v.form.tab2.client_name.$invalid"
id="client-name"
name="client-name"
trim
placeholder="Name of your OAuth 2.0 client"
v-model="form.tab2.client_name">
</b-form-input>
</b-form-group>
<div v-for="(redirect_uri, index) in form.tab2.redirect_uris" :key=index>
<b-form-row class="align-items-center">
<b-col>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
id="fieldset-10"
description="Enter your callback URL. The redirect_uri parameter must exactly match a URL in this list"
label="Redirect URI"
label-for="redirect-uri"
class="inputLabels"
>
<b-input-group>
<b-form-input
:state="!$v.form.tab2.redirect_uris.$each[index].$invalid"
id="redirect-uri"
name='redirect-uri'
trim
type="url"
v-model="form.tab2.redirect_uris[index]">
</b-form-input>
<b-input-group-append>
<b-button v-if="index > 0" @click="deleteRedirectUri(index)">Delete URI
</b-button>
<b-button @click="addRedirectUri(index)">Add another URI</b-button>
</b-input-group-append>
</b-input-group>
</b-form-group>
</b-col>
</b-form-row>
</div>
<b-form-group label="Scope:" class="inputLabels">
<b-form-checkbox-group
:options="scopeOptions"
id="scope"
name="scope"
v-model="form.tab2.scope"
>
<b-link href="https://www.cilogon.org/oidc#h.p_PEQXL8QUjsQm">Information on scopes</b-link>
</b-form-checkbox-group>
</b-form-group>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
description=""
id="fieldset-11"
label="Domain"
label-for="domain"
class="inputLabels"
>
<b-form-input
:state="!$v.form.tab2.domain.$invalid"
id="domain"
placeholder="idp.htrc.indiana.edu"
trim
v-model="form.tab2.domain">
</b-form-input>
</b-form-group>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
description=""
id="fieldset-1"
label="Client URI"
label-for="client-uri"
class="inputLabels"
>
<b-form-input
:state="!$v.form.tab2.client_uri.$invalid"
id="client-uri"
trim
v-model="form.tab2.client_uri">
</b-form-input>
</b-form-group>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
description=""
id="fieldset-12"
label="Logo URI"
label-for="logo-uri"
class="inputLabels"
>
<b-form-input
:state="!$v.form.tab2.logo_uri.$invalid"
id="logo-uri"
trim
type="url"
v-model="form.tab2.logo_uri">
</b-form-input>
</b-form-group>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
description=""
id="fieldset-8"
label="Parent Tenant ID"
label-for="client-id"
class="inputLabels"
:disabled="!form.tab2.parentID"
>
<b-form-input
:state="!$v.form.tab2.parentID.$invalid"
id="parent-id"
name="parent-id"
trim
v-model="form.tab2.parentID"
:disabled="!form.tab2.parentID"
readonly
>
</b-form-input>
</b-form-group>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
description=""
id="fieldset-8"
label="Parent Tenant Secret"
label-for="parent-secret"
class="inputLabels"
>
<b-form-input
:state="!$v.form.tab2.parentSecret.$invalid"
id="parent-secret"
name="parent-secret"
trim
v-model="form.tab2.parentSecret"
:disabled="!form.tab2.parentID"
>
</b-form-input>
</b-form-group>
<b-form-group
:invalid-feedback="invalidFeedback"
:valid-feedback="validFeedback"
id="fieldset-13"
label="Comment"
label-for="comment"
class="inputLabels"
>
<b-form-textarea
:state="!$v.form.tab2.comment.$invalid"
id="comment"
rows="3" textarea trim
placeholder="Provide description of the new tenant and any other comments here (at least 15 characters long) "
v-model="form.tab2.comment">
</b-form-textarea>
</b-form-group>
<b-form-group label="Application Type">
<b-form-radio-group
:options="application_typeOptions"
id="application-type"
name="application-type"
v-model="form.tab2.application_type"
></b-form-radio-group>
</b-form-group>
</div>
<div v-if="tabIndex === 3" class="content">
<div v-if="(this.clientID === ''&& !this.requestingTenant)">
<div class="row">
<div class="col">
<h1 class="h4 mb-4">Please create a new tenant to view ClientID and Client Secret</h1>
</div>
</div>
</div>
<div v-if="(this.requestingTenant)">
<div v-if="this.requestingTenant" class="text-center">
<b-spinner variant="primary" style="width: 3rem; height: 3rem;"
label="Large Spinner"></b-spinner>
</div>
</div>
<div v-if="(this.clientID !== ''&& !this.requestingTenant)">
<div class="row">
<div class="col">
<div class="card border-default">
<div class="card-body">
<table class="table">
<tbody>
<tr>
<th scope="row">Tenant ID</th>
<td>
<div> {{this.clientID}}</div>
</td>
</tr>
<tr>
<th scope="row">Tenant Secret</th>
<td>
<div> {{this.clientSecret}}</div>
</td>
</tr>
<tr>
<th scope="row">Tenant Status</th>
<td>
<div> {{this.status}}</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="text-center">
<b-button-group class="mt-2">
<b-button v-if="tabIndex > 1 && tabIndex <= 2" @click="tabIndex--" class="btnCustom">Previous
</b-button>
<b-button v-if="tabIndex == 1" @click="tabIndex++" class="btnCustom"
:disabled="enableNextButton(this.tabIndex)">Next
</b-button>
<b-button v-if="tabIndex == 2" class="btnCustom"
:disabled="enableNextButton(this.tabIndex)" type="submit">Create Tenant
</b-button>
</b-button-group>
</div>
</div>
</b-form>
</div>
</template>
<script>
import {email, required, minLength} from "vuelidate/lib/validators";
import config from "@/config";
export default {
props: {
requesterEmail: String,
tenantId: String
},
computed: {
state() {
return this.name.length >= 4 ? true : false
},
invalidFeedback() {
return ''
},
validFeedback() {
return ''
},
},
data() {
return {
tabIndex: 1,
isSubmitted: false,
custosId: "",
custosSec: "",
currentUserName: "",
user: "",
requestingTenant: false,
form: {
tab1: {
requester_email: "",
admin_username: "",
admin_first_name: "",
admin_last_name: "",
admin_email: "",
admin_password: "",
confirm_admin_password: "",
},
tab2: {
client_name: "",
redirect_uris: [""],
scope: "openid email profile org.cilogon.userinfo".split(" "),
domain: "",
client_uri: "",
logo_uri: "",
application_type: "web",
comment: "",
parentID: "",
parentSecret: "",
},
primary_contact: "",
secondary_contact: "",
},
scopeOptions: [
{text: "openId", value: "openid", disabled: "true"},
{text: "email", value: "email", disabled: "true"},
{text: "profile", value: "profile", disabled: "true"},
{text: "org.cilogon.userinfo", value: "org.cilogon.userinfo", disabled: "true"},
],
application_typeOptions: [
{text: "web", value: "web"},
],
clientID: 'testing-client',
clientSecret: 'testing-secret',
status:'REQUESTED'
}
},
validations: {
form: {
tab1: {
requester_email: {email},
admin_username: {required},
admin_first_name: {required},
admin_last_name: {required},
admin_email: {required},
admin_password: {
required,
strongPassword(admin_password) {
return (
/[a-z]/.test(admin_password) && // checks for a-z
/[0-9]/.test(admin_password) && // checks for 0-9
/\W|_/.test(admin_password) && // checks for special char
admin_password.length >= 8
);
}
},
confirm_admin_password: {
required,
strongPassword(confirm_admin_password) {
return (
// /[a-z]/.test(admin_password) && // checks for a-z
// /[0-9]/.test(admin_password) && // checks for 0-9
// /\W|_/.test(admin_password) && // checks for special char
// admin_password.length >= 8
confirm_admin_password == this.form.tab1.admin_password
);
}
},
},
tab2: {
client_name: {required},
scope: {required},
domain: {
required,
validDomain(domain) {
return (
/^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,}\.?((xn--)?([a-z0-9\-.]{1,61}|[a-z0-9-]{1,30})\.?[a-z]{2,})$/.test(domain)
)
}
},
client_uri: {
required,
validURL(client_uri) {
return (
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/.test(client_uri)
)
}
},
logo_uri: {
required,
validURL(logo_uri) {
return (
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/.test(logo_uri)
)
}
},
application_type: {required},
redirect_uris: {
$each: {
required,
validURL(url) {
return (
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/.test(url)
)
}
}
},
comment: {required, minLength: minLength(15)},
parentID: {},
parentSecret: {
validate(parentSecret) {
if (this.form.tab2.parentID) {
return (
parentSecret
)
} else {
return (
true
)
}
}
}
},
primary_contact: {required},
secondary_contact: {},
}
},
methods: {
isSubmitDisabled() {
if (!this.isSubmitted)
return this.$v.form.$invalid;
return this.isSubmitted;
},
linkClass(idx) {
if (this.tabIndex === idx) {
return ['bg-primary', 'text-light']
} else {
return ['bg-light', 'text-info']
}
},
onClickHandler(step) {
this.tabIndex = step;
},
async onSubmit(event) {
event.preventDefault();
this.isSubmitted = true;
this.requestingTenant = true
this.tabIndex++;
if (!this.$v.form.tab1.$invalid && !this.$v.form.tab2.$invalid) {
let requester_email = this.$v.form.tab1.admin_email.$model;
let admin_username = this.$v.form.tab1.admin_username.$model;
let admin_first_name = this.$v.form.tab1.admin_first_name.$model;
let admin_last_name = this.$v.form.tab1.admin_last_name.$model;
let admin_email = this.$v.form.tab1.admin_email.$model;
let admin_password = this.$v.form.tab1.admin_password.$model;
let client_name = this.$v.form.tab2.client_name.$model;
let redirect_uris = this.$v.form.tab2.redirect_uris.$model;
let scope = this.$v.form.tab2.scope.$model;
let domain = this.$v.form.tab2.domain.$model;
let client_uri = this.$v.form.tab2.client_uri.$model;
let logo_uri = this.$v.form.tab2.logo_uri.$model;
let comment = this.$v.form.tab2.comment.$model;
let application_type = this.$v.form.tab2.application_type.$model;
let scopeString = '';
for (var i = 0; i < scope.length; i++) {
scopeString += scope[i] + " "
}
scopeString = scopeString.trim()
let contacts = [];
contacts.push(requester_email);
let body = {
"client_name": client_name,
"requester_email": requester_email,
"admin_username": admin_username,
"admin_first_name": admin_first_name,
"admin_last_name": admin_last_name,
"admin_email": admin_email,
"contacts": contacts,
"redirect_uris": redirect_uris,
"scope": scopeString,
"domain": domain,
"admin_password": admin_password,
"client_uri": client_uri,
"logo_uri": logo_uri,
"application_type": application_type,
"comment": comment
}
if (this.$v.form.tab2.parentID.$model && this.$v.form.tab2.parentSecret.$model) {
let data = {
client_id: this.$v.form.tab2.parentID.$model,
client_sec: this.$v.form.tab2.parentSecret.$model,
body: body
}
let response = await this.$store.dispatch('tenant/createChildTenant', data)
this.clientID = response.client_id
this.clientSecret = response.client_secret
if (response.is_activated) {
this.status ="ACTIVE"
}
} else {
let data = {
body: body
}
let response = await this.$store.dispatch('tenant/createAdminTenant', data)
this.clientID = response.client_id
this.clientSecret = response.client_secret
if (response.is_activated) {
this.status ="ACTIVE"
}
}
this.requestingTenant = false
}
},
addRedirectUri: function () {
this.form.tab2.redirect_uris.push("");
},
deleteRedirectUri: function (index) {
if (index > 0) {
this.form.tab2.redirect_uris.splice(index, 1);
}
},
// eslint-disable-next-line no-unused-vars
enableNextButton(taboption) {
if (taboption == 1) {
return !!this.$v.form.tab1.$invalid
}
if (taboption == 2) {
return !!this.$v.form.tab2.$invalid
}
},
async sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
},
async mounted() {
this.custosId = config.value('clientId')
this.custosSec = config.value('clientSec')
this.currentUserName = await this.$store.dispatch('identity/getCurrentUserName')
let data = {
offset: 0, limit: 1, client_id: this.custosId, client_sec: this.custosSec,
username: this.currentUserName
}
let resp = await this.$store.dispatch('user/users', data)
if (Array.isArray(resp) && resp.length > 0) {
resp.forEach(obj => {
this.user = {
username: obj.username,
first_name: obj.first_name,
last_name: obj.last_name,
email: obj.email,
status: obj.state,
attributes: [],
roles: []
}
this.user = obj
this.form.tab1.admin_username = obj.username
this.form.tab1.admin_first_name = obj.first_name
this.form.tab1.admin_last_name = obj.last_name
this.form.tab1.admin_email = obj.email
})
}
this.form.tab2.parentID = this.$props.tenantId
}
}
</script>
<style scoped>
.btn:hover {
color: white;
background-color: #944203;
padding: 10px 25px;
border: 1px solid #944203;
border-radius: 8px;
}
.btn:focus {
color: white;
background-color: #944203;
padding: 10px 25px;
border: 1px solid #944203;
border-radius: 8px;
}
.link {
color: #ff6600;
}
.h-tab {
display: flex;
max-height: 500px;
margin-top: 20px;
padding: 20px;
}
.h-tabs {
flex: 8;
}
.tab-content {
flex: 1;
border-bottom: 3px solid black;
padding: 8px;
color: black;
font-weight: bold;
cursor: pointer;
font-size: 20px;
}
.tab-content-active {
flex: 1;
border-bottom: 3px solid #ff6600;;
padding: 8px;
color: #ff6600;
font-weight: bold;
cursor: pointer;
font-size: 20px;
}
.content {
margin-top: 20px;
width: 1000px;
margin-left: 35px;
}
.heading {
font-size: 30px;
color: black;
font-weight: bold;
}
.card {
padding: 25px;
}
.btnCustom {
color: white;
background-color: #ff6600;
padding: 10px 25px;
border: 1px solid #ff6600;
border-radius: 8px;
}
.btnCustom:hover {
color: white;
background-color: #944203;
padding: 10px 25px;
border: 1px solid #944203;
border-radius: 8px;
}
.btnCustom:focus {
color: white;
background-color: #944203;
padding: 10px 25px;
border: 1px solid #944203;
border-radius: 8px;
}
.inputLabels {
color: black;
font-weight: bold;
}
</style>