Skip to content

Commit

Permalink
Merge pull request #76 from fabiaserra/feature/sync_users
Browse files Browse the repository at this point in the history
`server` Simple support to sync users from SG over to Ayon
  • Loading branch information
jakubjezek001 authored Dec 2, 2024
2 parents 18f1970 + 9a1cebf commit bc21435
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 1 deletion.
1 change: 1 addition & 0 deletions frontend/dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

<body>
<h1>ShotGrid Sync</h1>
<button id="sync-users-button" class="sync-users-button" onclick="syncUsers();">Sync Users</button>
<p>
From this page you can Import projects from ShotGrid or trigger a project Sync!<br>
In order for the Synchronization to work, a <b><code>ShotgridProcessor</code> <a target="_parent" href="/services">service</a> must be running</b>, this page will only create <a target="_parent" href="/events"> events (with the topic: "shotgrid.event.project.sync") </a> for the processor to handle.
Expand Down
170 changes: 169 additions & 1 deletion frontend/dist/shotgrid-addon.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,174 @@ const populateTable = async () => {
}


const syncUsers = async () => {
/* Get all the Users from AYON and Shotgrid, then populate the table with their info
and a button to Synchronize if they pass the requirements */
ayonUsers = await getAyonUsers();
sgUsers = await getShotgridUsers();

sgUsers.forEach((sg_user) => {
let already_exists = false
ayonUsers.forEach((user) => {
if (sg_user.login == user.name) {
already_exists = true
}
})
if (!already_exists) {
createNewUserInAyon(
sg_user.id ,sg_user.login, sg_user.email, sg_user.name)
}
})
}


const getShotgridUsers = async () => {
/* Query Shotgrid for all active users. */
const sgBaseUrl = `${addonSettings.shotgrid_server.replace(/\/+$/, '')}/api/v1`
sgAuthToken = await axios
.post(`${sgBaseUrl}/auth/access_token`, {
client_id: `${addonSettings.service_settings.script_name}`,
client_secret: addonSettings.shotgrid_api_key,
grant_type: "client_credentials",
}, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json'
}
})
.then((result) => result.data.access_token)
.catch((error) => {
console.log("Unable to Acquire the Shotgrid Authorization Token!")
console.log(error)
});

sgUsers = await axios
.get(`${sgBaseUrl}/entity/human_users?filter[sg_status_list]=act&fields=login,name,email`, {
headers: {
'Authorization': `Bearer ${sgAuthToken}`,
'Accept': 'application/json'
}
})
.then((result) => result.data.data)
.catch((error) => {
console.log("Unable to Fetch Shotgrid Users!")
console.log(error)
});

/* Do some extra clean up on the users returned. */
var sgUsersConformed = []
users_to_ignore = ["dummy", "root", "support"]
if (sgUsers) {
sgUsers.forEach((sg_user) => {
if (
!users_to_ignore.some(item => sg_user.attributes.email.includes(item))
) {
sgUsersConformed.push({
"id": sg_user.id,
"login": sg_user.attributes.login,
"name": sg_user.attributes.name,
"email": sg_user.attributes.email,
})
}
});
}
return sgUsersConformed;
}


const getAyonUsers = async () => {
/* Query AYON for all existing users. */
ayonUsers = await axios({
url: '/graphql',
headers: {"Authorization": `Bearer ${accessToken}`},
method: 'post',
data: {
query: `
query ActiveUsers {
users {
edges {
node {
attrib {
email
fullName
}
active
name
}
}
}
}
`
}
}).then((result) => result.data.data.users.edges);

var ayonUsersConformed = []

if (ayonUsers) {
ayonUsers.forEach((user) => {
ayonUsersConformed.push({
"name": user.node.name,
"email": user.node.attrib.email,
"fullName": user.node.attrib.fullName,
})
})
}
return ayonUsersConformed
}

function validateLogin(login) {
// First sanitize by replacing @ with underscore
let new_login = login.replace(/@/g, '_');

// Ensure valid pattern
const validPattern = /^[a-zA-Z0-9][a-zA-Z0-9_\.\-]*[a-zA-Z0-9]$/;

if (!validPattern.test(new_login)) {
// If invalid, create valid string by:
// 1. Remove invalid chars
// 2. Ensure starts/ends with alphanumeric
let _new_login = new_login.replace(/[^a-zA-Z0-9_\.\-]/g, '')
.replace(/^[^a-zA-Z0-9]+/, '')
.replace(/[^a-zA-Z0-9]+$/, '');

// If result too short, append 'user'
if (_new_login.length < 2) {
new_login = 'user' + _new_login;
}
}

return new_login;
}

const createNewUserInAyon = async (id, login, email, name) => {
/* Spawn an AYON Event of topic "shotgrid.event" to synchcronize a project
from Shotgrid into AYON. */
call_result_paragraph = document.getElementById("call-result");

// make sure no @ and . or - is in login string
let fixed_login = validateLogin(login);

response = await ayonAPI
.put("/api/users/" + fixed_login, {
"active": true,
"attrib": {
"fullName": name,
"email": email,
},
"data": {
"sg_user_id": id
},
"password": login,
})
.then((result) => result)
.catch((error) => {
console.log("Unable to create user in AYON!")
console.log(error)
call_result_paragraph.innerHTML = `Unable to create user in AYON! ${error}`
});
}


const getShotgridProjects = async () => {
/* Query Shotgrid for all existing projects. */
const sgBaseUrl = `${addonSettings.shotgrid_server.replace(/\/+$/, '')}/api/v1`
Expand Down Expand Up @@ -159,7 +327,7 @@ const getShotgridProjects = async () => {

if (sgProjects) {
sgProjects.forEach((project) => {
sgProjectsConformed.push({
sgProjectsConformed.push({
"name": project.attributes.name,
"code": project.attributes[`${addonSettings.shotgrid_project_code_field}`],
"shotgridId": project.id,
Expand Down

0 comments on commit bc21435

Please sign in to comment.