Skip to content

feat(front): add service accounts feature #435

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ee/rbac/assets/permissions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ permissions:
description: "View the existing dashboards within the organization."
- name: "organization.dashboards.manage"
description: "Create new dashboard views."
- name: "organization.service_accounts.view"
description: "View service accounts within the organization."
- name: "organization.service_accounts.manage"
description: "Manage service accounts within the organization."
project:
- name: "project.view"
description: "Access the project. This permission is needed to see any page within the project."
Expand Down
4 changes: 4 additions & 0 deletions ee/rbac/assets/roles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ roles:
- "organization.custom_roles.view"
- "organization.dashboards.view"
- "organization.dashboards.manage"
- "organization.service_accounts.view"
- "organization.service_accounts.manage"
- name: "Admin"
description: "Admins can modify settings within the organization or any of its projects. However, they do not have access to billing information, and they cannot change general organization details, such as the organization name and URL."
maps_to: "Admin"
Expand Down Expand Up @@ -77,6 +79,8 @@ roles:
- "organization.dashboards.view"
- "organization.dashboards.manage"
- "project.delete"
- "organization.service_accounts.view"
- "organization.service_accounts.manage"
- name: "Member"
description: "Members can access the organization's homepage and the projects they are assigned to. However, they are not able to modify any settings."
permissions:
Expand Down
2 changes: 1 addition & 1 deletion front/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ RUN mix sentry_recompile && mix compile --warnings-as-errors
# -- elixir stage

# -- node stage
FROM node:16-alpine as node
FROM node:16-alpine AS node
WORKDIR /assets
COPY front/assets/package.json front/assets/package-lock.json ./
RUN npm set progress=false && npm install
Expand Down
3 changes: 3 additions & 0 deletions front/assets/css/app-semaphore.css
Original file line number Diff line number Diff line change
Expand Up @@ -2795,6 +2795,8 @@ img { max-width: 100%; }
.b--indigo { border-color: #1570ff; }
.b--dark-indigo { border-color: #00359f; }
.b--orange { border-color: #fd7e14; }
.b--yellow { border-color: #FBC335; }
.b--blue { border-color: #2196F3; }
.b--purple { border-color: #8658d6; }
.b--dark-purple { border-color: #5122a5; }
.b--dark-brown { border-color: #974510; }
Expand Down Expand Up @@ -4585,6 +4587,7 @@ code, .code, pre {
.bg-washed-purple { background-color: #f3ecff; }
/* Yellows */
.yellow { color: #FBC335; }
.gold { color: #FBC335; }
.lightest-yellow { color: #fff3bf; }
.washed-yellow { color: #fffae4; }
.bg-yellow { background-color: #FBC335; }
Expand Down
25 changes: 19 additions & 6 deletions front/assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import { default as Agents} from "./agents";
import { default as AddPeople } from "./people/add_people";
import { default as EditPerson } from "./people/edit_person";
import { default as SyncPeople } from "./people/sync_people";
import { default as ServiceAccounts } from "./service_accounts";
import { default as Report } from "./report";

import { InitializingScreen } from "./project_onboarding/initializing";
Expand Down Expand Up @@ -294,12 +295,23 @@ export var App = {
GroupManagement.init();
new Star();

const addPeopleAppRoot = document.getElementById("add-people");
if (addPeopleAppRoot) {
AddPeople({
dom: addPeopleAppRoot,
config: addPeopleAppRoot.dataset,
});

// Initialize Preact apps
const serviceAccountsEl = document.getElementById("service-accounts");
if (serviceAccountsEl) {
const config = JSON.parse(serviceAccountsEl.dataset.config);
ServiceAccounts({ dom: serviceAccountsEl, config });
}

const addPeopleEl = document.getElementById("add-people");
if (addPeopleEl) {
AddPeople({ dom: addPeopleEl, config: addPeopleEl.dataset });
}

const syncPeopleEl = document.querySelector(".app-sync-people");
if (syncPeopleEl) {
const config = JSON.parse(syncPeopleEl.dataset.config);
SyncPeople({ dom: syncPeopleEl, config });
}

document.querySelectorAll(".app-edit-person").forEach((editPersonAppRoot) => {
Expand Down Expand Up @@ -516,6 +528,7 @@ export var App = {

window.Notice.init();


$(document).on("click", ".x-select-on-click", function (event) {
event.currentTarget.setSelectionRange(0, event.currentTarget.value.length);
});
Expand Down
31 changes: 12 additions & 19 deletions front/assets/js/people/add_people/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const App = () => {
<span className="material-symbols-outlined mr2">person_add</span>
{`Add people`}
</button>
<Modal isOpen={isOpen} close={() => close(false)} title="Add people">
<Modal isOpen={isOpen} close={() => close(false)} title="Add new people" width="w-70-m">
<AddNewUsers close={close}/>
</Modal>
</Fragment>
Expand Down Expand Up @@ -85,7 +85,7 @@ const AddNewUsers = (props: { close: (reload: boolean) => void, }) => {
const Link = (props: { icon: VNode, title: string, }) => {
return (
<ActiveShadowLink
className={`btn btn-secondary ${
className={`flex-grow-1 btn btn-secondary ${
currentProvider === provider ? `active` : ``
}`}
disabled={loading}
Expand Down Expand Up @@ -134,16 +134,9 @@ const AddNewUsers = (props: { close: (reload: boolean) => void, }) => {
};

return (
<div
className="bg-white br3 shadow-1 w-90 w-70-m mw6 relative popup"
style={{ top: `200px`, transform: `translate(-50%, 0)` }}
>
<div className="flex items-center justify-between ph4 pt4 mb3">
<h2 className="f3 mb0">Add new people</h2>
</div>

<div className="pa4">
{userProviders.length > 1 && (
<div className="mb3 button-group ph4 w-100 items-center justify-center">
<div className="mb3 button-group w-100 items-center">
{userProviders.map(userProviderBox)}
</div>
)}
Expand All @@ -158,7 +151,7 @@ const AddNewUsers = (props: { close: (reload: boolean) => void, }) => {
return (
<Fragment key={idx}>
{loading && (
<div className="ph4 pb4 tc">
<div className="pb4 tc">
<toolbox.Asset path="images/spinner.svg"/>
</div>
)}
Expand Down Expand Up @@ -280,7 +273,7 @@ const ProvideVia = (props: ProvideViaProps) => {
return (
<Fragment>
<div className="ph4 pb4">{message}</div>
<div className="flex justify-end items-center mt2 pb4 ph4">
<div className="flex justify-end items-center mt2">
<button
className="btn btn-primary ml3"
onClick={() => props?.onCancel(anyInvites)}
Expand All @@ -294,11 +287,11 @@ const ProvideVia = (props: ProvideViaProps) => {

return (
<Fragment>
<div className="ph4">
<div className="">
<label className="db mb2">Invite users to join your organization</label>
</div>
<div
className="ph4 pv1 w-100"
className="pv1 ph1 w-100"
style={{ maxHeight: `400px`, overflow: `auto` }}
>
{!props.noManualInvite && (
Expand Down Expand Up @@ -370,7 +363,7 @@ const ProvideVia = (props: ProvideViaProps) => {
</div>

{collaborators.length != 0 && (
<div className="flex justify-end items-center mt2 pb4 ph4">
<div className="flex justify-end items-center mt2">
<a
className="gray underline pointer"
onClick={() => setSelectedCollaborators(collaborators)}
Expand Down Expand Up @@ -513,7 +506,7 @@ const ProvideViaEmail = (props: ProvideViaEmailProps) => {

return (
<Fragment>
<div className="ph4" style={{ maxHeight: `400px`, overflow: `auto` }}>
<div className="ph1" style={{ maxHeight: `400px`, overflow: `auto` }}>
{!arePeopleInvited && (
<label className="db mb2">Email addresses and usernames</label>
)}
Expand Down Expand Up @@ -593,7 +586,7 @@ const ProvideViaEmail = (props: ProvideViaEmailProps) => {
))}
</div>
{arePeopleInvited && (
<div className="flex justify-end pb4 ph4">
<div className="flex justify-end">
<button
className="btn btn-primary"
onClick={() => props?.onCancel(true)}
Expand All @@ -603,7 +596,7 @@ const ProvideViaEmail = (props: ProvideViaEmailProps) => {
</div>
)}
{!arePeopleInvited && (
<div className="flex justify-end pb4 ph4">
<div className="flex justify-end">
<button
className="btn btn-secondary mr3"
onClick={() => props?.onCancel(false)}
Expand Down
24 changes: 18 additions & 6 deletions front/assets/js/people/add_to_project.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export var AddToProject = {
if(modal){
var addPeopleToProjectBtn = document.getElementById("add_people_to_project");
var addGroupsToProjectBtn = document.getElementById("add_group_to_project");
var addServiceAccountsToProjectBtn = document.getElementById("add_service_accounts_to_project");
var cancelModalBtn = document.getElementById("cancel_btn");

if(addPeopleToProjectBtn){
Expand All @@ -37,6 +38,13 @@ export var AddToProject = {
}
}

if(addServiceAccountsToProjectBtn){
addServiceAccountsToProjectBtn.onclick = () => {
modal.style.display = "block";
this.initProjectNonMembersFilter("service_account")
}
}

cancelModalBtn.onclick = () => {
this.selectedUserIds = []
document.getElementById('users').innerHTML = ''
Expand Down Expand Up @@ -137,9 +145,11 @@ export var AddToProject = {
let assets_path = document.querySelector("meta[name='assets-path']").getAttribute("content")

return `<span ${props}>
${result.has_avatar
? `<img src="${result.avatar}" class="ba b--black-50 br-100 mr2" width="32">`
: `<img src="${assets_path}/images/org-${result.name.charAt(0).toLowerCase()}.svg" class="bg-washed-gray w2 h2 br-100 mr2 ba b--black-50"></div>`
${result.subject_type === "service_account"
? `<div class="dib w2 h2 br-100 mr2 ba b--black-50 tc bg-light-gray"><span class="material-symbols-outlined f6 gray" style="line-height: 2;">smart_toy</span></div>`
: result.has_avatar
? `<img src="${result.avatar}" class="ba b--black-50 br-100 mr2" width="32">`
: `<img src="${assets_path}/images/org-${result.name.charAt(0).toLowerCase()}.svg" class="bg-washed-gray w2 h2 br-100 mr2 ba b--black-50"></div>`
}
<span>${escapeHtml(result.name)}</span>
</span>`
Expand Down Expand Up @@ -180,9 +190,11 @@ export var AddToProject = {
`
<div id="${user.id}" class="flex items-center justify-between bg-white shadow-1 mv1 mh1 ph3 pv2 br3">
<div class="flex items-center">
${user.has_avatar
? `<img src="${user.avatar}" class="w2 h2 br-100 mr2 ba b--black-50">`
: `<img src="${assets_path}/images/org-${user.name.charAt(0).toLowerCase()}.svg" class="bg-washed-gray w2 h2 br-100 mr2 ba b--black-50">`
${user.subject_type === "service_account"
? `<div class="w2 h2 br-100 mr2 ba b--black-50 flex items-center justify-center bg-light-gray"><span class="material-symbols-outlined f6 gray">smart_toy</span></div>`
: user.has_avatar
? `<img src="${user.avatar}" class="w2 h2 br-100 mr2 ba b--black-50">`
: `<img src="${assets_path}/images/org-${user.name.charAt(0).toLowerCase()}.svg" class="bg-washed-gray w2 h2 br-100 mr2 ba b--black-50">`
}
<div class="flex items-center">
<div class="b">${escapeHtml(user.name)}</div>
Expand Down
77 changes: 36 additions & 41 deletions front/assets/js/people/edit_person/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,53 +163,48 @@ export const Button = () => {
<span className="material-symbols-outlined mr1">manage_accounts</span>
<span>Edit</span>
</button>
<toolbox.Modal isOpen={isOpen} close={close} title="Add people">
<div className="bg-white br3 shadow-1 w-90 w-50-m mw6 relative popup">
<div className="pa3">
<div className="flex items-center justify-between mb3">
<h2 className="f3 mb0">Edit user</h2>
</div>
<div className="mb3">
<label className="db mb2 b">Email address</label>
<div className="flex">
<input
type="email"
className="form-control w-100"
value={email}
onChange={onEmailChanged}
disabled={emailResponse.status == `loading`}
/>
</div>
<ResponseHandler response={emailResponse}/>
<toolbox.Modal isOpen={isOpen} close={close} title="Edit user">
<div className="pa3">
<div className="mb3">
<label className="db mb2 b">Email address</label>
<div className="flex">
<input
type="email"
className="form-control w-100"
value={email}
onChange={onEmailChanged}
disabled={emailResponse.status == `loading`}
/>
</div>
<ResponseHandler response={emailResponse}/>
</div>

<div className="mb3">
<label className="db mb2 b">Password</label>
<PasswordReset user={user}/>
</div>
<div className="mb3">
<label className="db mb2 b">Password</label>
<PasswordReset user={user}/>
</div>

<div>
<label className="db mb2 b">Role</label>
<ChangeRole
user={user}
selectRole={setSelectedRole}
selectedRole={selectedRole}
/>
<ResponseHandler response={roleResponse}/>
</div>
<div className="flex justify-end mt4">
<button className="btn btn-secondary mr3" onClick={close}>
<div>
<label className="db mb2 b">Role</label>
<ChangeRole
user={user}
selectRole={setSelectedRole}
selectedRole={selectedRole}
/>
<ResponseHandler response={roleResponse}/>
</div>
<div className="flex justify-end mt4">
<button className="btn btn-secondary mr3" onClick={close}>
Cancel
</button>
</button>

<button
className="btn btn-primary"
onClick={save}
disabled={!roleChanged && !emailChanged}
>
<button
className="btn btn-primary"
onClick={save}
disabled={!roleChanged && !emailChanged}
>
Save changes
</button>
</div>
</button>
</div>
</div>
</toolbox.Modal>
Expand Down
Loading