Skip to content
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

CRISTAL-381: Make the github backend supported #687

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

pjeanjean
Copy link
Contributor

Jira URL

https://jira.xwiki.org/browse/CRISTAL-381

Changes

Description

  • Working authentication
  • Content display
  • Content edition
  • Content deletion
  • Updated navigation tree to use public API
  • Updated history to use public API

Clarifications

Login operations for the GitHub API have to be done in the backend. As such, a new backend has been implemented in ./github-authentication. It requires to set a Client ID for a GitHub app that has repo:read and repo:write permissions for the repository the user wants to use. This can be set in ./github-authentication/src/config.ts.

While working on this issue, I noticed that the transformImage was not working properly (i.e., mutation listeners were in fact not triggered on document change). I don't know since when this happens, but I added a simpler transformImagesInElements() function that should have, as an added benefit, less performance impact for this purpose.

Screenshots & Video

image
image

Executed Tests

Each new and changed feature was tested manually, and the current test suite was run manually.

Expected merging strategy

  • Prefers squash: Yes
  • Backport on branches:
    • N/A

* Working authentication
* Content display
* Content edition
* Content deletion
* Updated navigation tree to use public API
* Updated history to use public API
private readonly accessTokenCookieKeyPrefix = "accessToken";

async start(): Promise<void> {
const authorizationUrl = new URL("http://localhost:15682/device-login");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this URL be defined in the configuration?

} = await response.json();

window.localStorage.setItem(
"currentConfigName",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are all the string constants defined in fields but not this one?

@@ -29,7 +29,7 @@ interface AuthenticationManager {
/**
* Starts the authentication process.
*/
start(): void;
start(): Promise<void>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the signature changes, we need to update the since for this method

let expiresIn: number =
parseInt(window.localStorage.getItem(this.localStorageExpiresIn)!) * 1000;

const intervalId = setInterval(async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block deserves an explanation, and possible to be isolated in a private method, feels hard to understand without carefully reading the code.

parseInt(window.localStorage.getItem(this.localStorageExpiresIn)!) * 1000;

const intervalId = setInterval(async () => {
fetch(verificationUrl).then(async (response) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await is preferable over then in async methods

jsonResponse.token_type!,
cookiesOptions,
);
window.location.reload();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this working on electron?

let expirationSeconds: number = parseInt(
window.localStorage.getItem(localStorageExpiresIn)!,
);
const intervalId = setInterval(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this deserves a comment

</x-btn>
</template>
<template #default>
Step 1: Copy the following code
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing translations

@@ -52,8 +52,8 @@ function logout() {
<template v-if="!error">
<i18n-t keypath="userDescription" tag="span">
<a :href="profile">
<x-avatar v-if="avatar" :image="avatar" :name="name"></x-avatar>
{{ name }}
<x-avatar v-if="avatar" :image="avatar" :name="name"></x-avatar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unwanted change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was actually wanted, I forgot to mention it. With the previous version, the underline of the link was applied across the avatar image as well, which was quite disturbing.

},
}).href,
};
jsonResponse.forEach(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while not "officially" voted, it seems like using for ... of is preferable over forEach, see https://github.com/github/eslint-plugin-github/blob/main/docs/rules/array-foreach.md

});
const jsonResponse = await response.json();
jsonResponse.payload.tree.items.forEach(
(treeNode: { name: string; path: string; contentType: string }) => {
console.log(jsonResponse);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leftover debug log?

const config = {
GITHUB_DEVICE_LOGIN_URL: "https://github.com/login/device/code",
GITHUB_DEVICE_VERIFY_URL: "https://github.com/login/oauth/access_token",
GITHUB_APP_CLIENT_ID: "",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it required to update this value and recompile to have a working instance with a Github backend?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, got it, this is specifically for the third party github auth server, ok for now

if (cristal && contentRoot.value) {
ContentTools.listenToClicks(contentRoot.value, cristal);
ContentTools.transformMacros(contentRoot.value, cristal);
ContentTools.transformImagesInElement(contentRoot.value, cristal);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not seems related to the PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was, actually, kind of. We did not catch that image transformation stopped working with the current backends because images are supposed to be handled as attachments, and the GitHub backend is the one right now that actually uses it (to display images stored in the repository).

"configType": "GitHub",
"serverRendering": false,
"offline": false,
"baseURL": "https://raw.githubusercontent.com/ldubost/test/master/",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for confirmation, this means that a config entry is currently required for each repo we want to give access to in a given Cristal instance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, yes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I suggest creating a Jira issue for improving that (and other limitations you know of) so that we have a clear vision of where we are at.

.get()
?.getAuthorizationHeader();
const headers: { Accept: string; Authorization?: string } = {
Accept: "application/json",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing authentication headers

@manuelleduc
Copy link
Contributor

  • edit is displayed even when not logged in
  • missing header on history query
  • for now, we'll keep using the same json based storage, we'll switch for all backends at once (makes it easier to support internal links, new pages creation and attachments)
  • document all the setup in the wiki

@manuelleduc
Copy link
Contributor

  1. introduce authentication-github-ui
  2. load it from github.ts in lib
  3. move GitHubLoginMenu.vue in authentication-github-ui and define an extension UI component for it, with a sidebar.actions UIXP
  4. update GitHubLoginMenu.vue to have an empty activator (see AttachmentPreview.vue for inspiration)
  5. on GitHubAuthenticationManager.start change the vmodel of GitHubLoginMenu.vue to make the modal visible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants