Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
7925951
tester
GregoryTravis Sep 23, 2025
c63801f
wip
GregoryTravis Sep 24, 2025
1ef8e0e
import style, open lib
GregoryTravis Sep 24, 2025
eb911d0
initial open
GregoryTravis Sep 24, 2025
5fb6e5e
get auth code
GregoryTravis Sep 24, 2025
ddc2e2d
return auth code, ignore favicon
GregoryTravis Sep 24, 2025
25595da
post, but failing for no grant_type
GregoryTravis Sep 24, 2025
514f64f
try axios
GregoryTravis Sep 24, 2025
5b5692c
got at
GregoryTravis Sep 25, 2025
5646c0d
async
GregoryTravis Sep 25, 2025
5f61fa9
ac+at combined function
GregoryTravis Sep 25, 2025
8a20fa0
separate ac and at
GregoryTravis Sep 25, 2025
f8e8396
successful call to /me
GregoryTravis Sep 25, 2025
64205d8
wip
GregoryTravis Sep 25, 2025
2cf0f74
id keys
GregoryTravis Sep 25, 2025
8307b77
id vars
GregoryTravis Sep 25, 2025
08be34e
works
GregoryTravis Oct 7, 2025
7ba2b7f
Merge branch 'develop' into wip/gmt/12929-ms-oauth
GregoryTravis Oct 7, 2025
6dde986
wip
GregoryTravis Oct 7, 2025
3368612
wip
GregoryTravis Oct 7, 2025
e6d79e7
build, dev-env client ids
GregoryTravis Oct 7, 2025
bef9563
Merge branch 'develop' into wip/gmt/12929-ms-oauth
GregoryTravis Oct 8, 2025
0828b7c
Merge branch 'develop' into wip/gmt/12929-ms-oauth
GregoryTravis Oct 9, 2025
228e32c
extra scopes
GregoryTravis Oct 9, 2025
79a2749
remove oauth
GregoryTravis Oct 9, 2025
6618e70
revert
GregoryTravis Oct 9, 2025
e7f43f0
changelog
GregoryTravis Oct 9, 2025
815d5b6
Merge branch 'develop' into wip/gmt/12929-ms-oauth
GregoryTravis Oct 10, 2025
0fc7163
update dev-env
GregoryTravis Oct 13, 2025
be3b6b9
update dev-env
GregoryTravis Oct 13, 2025
266742c
update dev-env
GregoryTravis Oct 13, 2025
7b72e3b
update dev-env
GregoryTravis Oct 13, 2025
afe312e
Merge branch 'develop' into wip/gmt/12929-ms-oauth
GregoryTravis Oct 13, 2025
32a24df
update dev-env
GregoryTravis Oct 13, 2025
880c948
decode_as_json
GregoryTravis Oct 14, 2025
561ce79
just rename enso lib instances
GregoryTravis Oct 14, 2025
ba4c742
wip
GregoryTravis Oct 14, 2025
4fada58
dropdown name
GregoryTravis Oct 14, 2025
9b03222
revert bazel lock
GregoryTravis Oct 15, 2025
6e80534
doc methods
GregoryTravis Oct 15, 2025
055e524
api
GregoryTravis Oct 15, 2025
3966dcd
prettier
GregoryTravis Oct 15, 2025
7ce7665
Merge branch 'develop' into wip/gmt/12929-ms-oauth
GregoryTravis Oct 15, 2025
a9bee23
update dev-env
GregoryTravis Oct 17, 2025
db87c39
no comma between scopes
GregoryTravis Oct 20, 2025
6928e51
Merge branch 'develop' into wip/gmt/12929-ms-oauth
GregoryTravis Oct 23, 2025
0c4a827
fix merge
GregoryTravis Oct 23, 2025
af7e237
merge
GregoryTravis Oct 24, 2025
49c526f
Merge branch 'develop' into wip/gmt/12929-ms-oauth
GregoryTravis Oct 24, 2025
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
2 changes: 2 additions & 0 deletions .github/workflows/ide-packaging-optional.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ jobs:
ENSO_IDE_MAPBOX_API_TOKEN: ${{ vars.ENSO_MAPBOX_API_TOKEN }}
ENSO_IDE_SENTRY_DSN: ${{ vars.ENSO_CLOUD_SENTRY_DSN }}
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_STRAVA_OAUTH_CLIENT_ID }}
ENSO_IDE_MS365_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_MS365_OAUTH_CLIENT_ID }}
ENSO_IDE_STRIPE_KEY: ${{ vars.ENSO_CLOUD_STRIPE_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- if: "${{ (always()) && (contains(github.event.pull_request.labels.*.name, 'CI: Clean build required') || (github.ref == 'refs/heads/develop') || inputs.clean_build_required) }}"
Expand Down Expand Up @@ -208,6 +209,7 @@ jobs:
ENSO_IDE_MAPBOX_API_TOKEN: ${{ vars.ENSO_MAPBOX_API_TOKEN }}
ENSO_IDE_SENTRY_DSN: ${{ vars.ENSO_CLOUD_SENTRY_DSN }}
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_STRAVA_OAUTH_CLIENT_ID }}
ENSO_IDE_MS365_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_MS365_OAUTH_CLIENT_ID }}
ENSO_IDE_STRIPE_KEY: ${{ vars.ENSO_CLOUD_STRIPE_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload ide
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/ide-packaging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ jobs:
ENSO_IDE_MAPBOX_API_TOKEN: ${{ vars.ENSO_MAPBOX_API_TOKEN }}
ENSO_IDE_SENTRY_DSN: ${{ vars.ENSO_CLOUD_SENTRY_DSN }}
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_STRAVA_OAUTH_CLIENT_ID }}
ENSO_IDE_MS365_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_MS365_OAUTH_CLIENT_ID }}
ENSO_IDE_STRIPE_KEY: ${{ vars.ENSO_CLOUD_STRIPE_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload gui
Expand Down Expand Up @@ -263,6 +264,7 @@ jobs:
ENSO_IDE_MAPBOX_API_TOKEN: ${{ vars.ENSO_MAPBOX_API_TOKEN }}
ENSO_IDE_SENTRY_DSN: ${{ vars.ENSO_CLOUD_SENTRY_DSN }}
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_STRAVA_OAUTH_CLIENT_ID }}
ENSO_IDE_MS365_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_MS365_OAUTH_CLIENT_ID }}
ENSO_IDE_STRIPE_KEY: ${{ vars.ENSO_CLOUD_STRIPE_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- if: "${{ (always()) && (contains(github.event.pull_request.labels.*.name, 'CI: Clean build required') || (github.ref == 'refs/heads/develop') || inputs.clean_build_required) }}"
Expand Down Expand Up @@ -336,6 +338,7 @@ jobs:
ENSO_IDE_MAPBOX_API_TOKEN: ${{ vars.ENSO_MAPBOX_API_TOKEN }}
ENSO_IDE_SENTRY_DSN: ${{ vars.ENSO_CLOUD_SENTRY_DSN }}
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_STRAVA_OAUTH_CLIENT_ID }}
ENSO_IDE_MS365_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_MS365_OAUTH_CLIENT_ID }}
ENSO_IDE_STRIPE_KEY: ${{ vars.ENSO_CLOUD_STRIPE_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload ide
Expand Down Expand Up @@ -439,6 +442,7 @@ jobs:
ENSO_IDE_MAPBOX_API_TOKEN: ${{ vars.ENSO_MAPBOX_API_TOKEN }}
ENSO_IDE_SENTRY_DSN: ${{ vars.ENSO_CLOUD_SENTRY_DSN }}
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_STRAVA_OAUTH_CLIENT_ID }}
ENSO_IDE_MS365_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_MS365_OAUTH_CLIENT_ID }}
ENSO_IDE_STRIPE_KEY: ${{ vars.ENSO_CLOUD_STRIPE_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.MICROSOFT_CODE_SIGNING_CERT_PASSWORD }}
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ jobs:
ENSO_IDE_SENTRY_ORGANIZATION: ${{ vars.ENSO_CLOUD_SENTRY_ORGANIZATION }}
ENSO_IDE_SENTRY_PROJECT: ${{ vars.ENSO_CLOUD_SENTRY_PROJECT }}
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_STRAVA_OAUTH_CLIENT_ID }}
ENSO_IDE_MS365_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_MS365_OAUTH_CLIENT_ID }}
ENSO_IDE_STRIPE_KEY: ${{ vars.ENSO_CLOUD_STRIPE_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
Expand Down Expand Up @@ -656,6 +657,7 @@ jobs:
ENSO_IDE_SENTRY_ORGANIZATION: ${{ vars.ENSO_CLOUD_SENTRY_ORGANIZATION }}
ENSO_IDE_SENTRY_PROJECT: ${{ vars.ENSO_CLOUD_SENTRY_PROJECT }}
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_STRAVA_OAUTH_CLIENT_ID }}
ENSO_IDE_MS365_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_MS365_OAUTH_CLIENT_ID }}
ENSO_IDE_STRIPE_KEY: ${{ vars.ENSO_CLOUD_STRIPE_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
Expand Down Expand Up @@ -738,6 +740,7 @@ jobs:
ENSO_IDE_SENTRY_ORGANIZATION: ${{ vars.ENSO_CLOUD_SENTRY_ORGANIZATION }}
ENSO_IDE_SENTRY_PROJECT: ${{ vars.ENSO_CLOUD_SENTRY_PROJECT }}
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_STRAVA_OAUTH_CLIENT_ID }}
ENSO_IDE_MS365_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_MS365_OAUTH_CLIENT_ID }}
ENSO_IDE_STRIPE_KEY: ${{ vars.ENSO_CLOUD_STRIPE_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
Expand Down Expand Up @@ -814,6 +817,7 @@ jobs:
ENSO_IDE_SENTRY_ORGANIZATION: ${{ vars.ENSO_CLOUD_SENTRY_ORGANIZATION }}
ENSO_IDE_SENTRY_PROJECT: ${{ vars.ENSO_CLOUD_SENTRY_PROJECT }}
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_STRAVA_OAUTH_CLIENT_ID }}
ENSO_IDE_MS365_OAUTH_CLIENT_ID: ${{ secrets.ENSO_IDE_MS365_OAUTH_CLIENT_ID }}
ENSO_IDE_STRIPE_KEY: ${{ vars.ENSO_CLOUD_STRIPE_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@
- [Add EDI_Format and support for reading ANSI X12 EDI files.][14158]
- [Add support for reading xlsb Excel file format][14157]
- [Add Text_Column.upper and Text_Column.lower.][14179]
- [Microsoft 365 OAuth support.][14135]
- [Add Text_Column.proper and Rename Case.Title->Case.Proper.][14184]

[13769]: https://github.com/enso-org/enso/pull/13769
[14026]: https://github.com/enso-org/enso/pull/14026
[14039]: https://github.com/enso-org/enso/pull/14039
[14085]: https://github.com/enso-org/enso/pull/14085
[14091]: https://github.com/enso-org/enso/pull/14091
[14135]: https://github.com/enso-org/enso/pull/14135
[14158]: https://github.com/enso-org/enso/pull/14158
[14157]: https://github.com/enso-org/enso/pull/14157
[14179]: https://github.com/enso-org/enso/pull/14179
Expand Down
7 changes: 7 additions & 0 deletions app/common/src/services/Backend/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,15 @@ export interface StravaCredentialInput {
readonly scopes: readonly string[]
}

/** User settings for an MS365 credential. */
export interface MS365CredentialInput {
readonly type: 'MS365'
readonly scopes: readonly string[]
}

/** User settings for an arbitrary credential. */
export type CredentialInput =
| SnowflakeCredentialInput
| GoogleCredentialInput
| StravaCredentialInput
| MS365CredentialInput
5 changes: 5 additions & 0 deletions app/common/src/text/english.json
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@
"stravaCredentialScopesEmptyError": "Please select at least one scope for the integration.",
"stravaCredentialReadScope": "Read",
"stravaCredentialActivityReadScope": "Read Activity",
"ms365CredentialType": "Microsoft 365",
"ms365CredentialScopes": "Scopes",
"ms365CredentialScopesEmptyError": "Please select at least one scope for the integration.",
"ms365CredentialUserReadScope": "Read Profile",
"ms365CredentialFilesReadScope": "Read Files",
"credentialServiceName": "Credential for service",
"credentialState": "State",
"credentialStateReady": "Ready to be used",
Expand Down
1 change: 1 addition & 0 deletions app/gui/.env.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ ENSO_IDE_AUTH_ENDPOINT = "((%__ENSO_IDE_AUTH_ENDPOINT__%))"
ENSO_IDE_VERSION = "((%__ENSO_IDE_VERSION__%))"
ENSO_IDE_GOOGLE_OAUTH_CLIENT_ID = "((%__ENSO_IDE_GOOGLE_OAUTH_CLIENT_ID__%))"
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID = "((%__ENSO_IDE_STRAVA_OAUTH_CLIENT_ID__%))"
ENSO_IDE_MS365_OAUTH_CLIENT_ID = "((%__ENSO_IDE_MS365_OAUTH_CLIENT_ID__%))"
1 change: 1 addition & 0 deletions app/gui/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const $config = {
AG_GRID_LICENSE_KEY: import.meta.env.ENSO_IDE_AG_GRID_LICENSE_KEY,
GOOGLE_OAUTH_CLIENT_ID: import.meta.env.ENSO_IDE_GOOGLE_OAUTH_CLIENT_ID,
STRAVA_OAUTH_CLIENT_ID: import.meta.env.ENSO_IDE_STRAVA_OAUTH_CLIENT_ID,
MS365_OAUTH_CLIENT_ID: import.meta.env.ENSO_IDE_MS365_OAUTH_CLIENT_ID,
MAPBOX_API_TOKEN: window.api?.mapBoxApiToken() || import.meta.env.ENSO_IDE_MAPBOX_API_TOKEN,
} as const

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* @file
* Dialog for an MS365 credential.
* Remember to ensure this component is added to `CREDENTIAL_INFOS` in `constants.ts`.
*/

import { Checkbox } from '#/components/Checkbox'
import { Form } from '#/components/Form'
import { Input } from '#/components/Inputs/Input'
import { useToastAndLog } from '#/hooks/toastAndLogHooks'
import { useText } from '$/providers/react'
import { CredentialsFormFooter } from './CredentialsFormFooter'
import * as ms365 from './ms365'
import type { CredentialFormProps } from './types'

/** Dialog for a MS365 credential. */
export function MS365CredentialsForm(props: CredentialFormProps) {
const { createCredentials } = props
const { getText } = useText()
const toastAndLog = useToastAndLog()

return (
<Form
method="dialog"
schema={ms365.FORM_SCHEMA}
defaultValues={{
scopes: ['User.Read', 'Files.Read'],
}}
className="w-full"
onSubmit={async (values) => {
try {
await ms365.submitForm(createCredentials, values)
} catch (error) {
toastAndLog(null, error)
}
}}
>
{(form) => (
<>
<Input form={form} name="name" label={getText('name')} />
<Checkbox.Group form={form} name="scopes" label={getText('ms365CredentialScopes')}>
<Checkbox value="User.Read">{getText('ms365CredentialUserReadScope')}</Checkbox>
<Checkbox value="Files.Read">{getText('ms365CredentialFilesReadScope')}</Checkbox>
</Checkbox.Group>
<CredentialsFormFooter isCreating={true} canCancel={false} canReset={false} />
</>
)}
</Form>
)
}
7 changes: 7 additions & 0 deletions app/gui/src/dashboard/data/serviceCredentials/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/** @file Constants related to credential dialogs. */
import { GoogleCredentialsForm } from '#/data/serviceCredentials/GoogleCredentialsForm'
import { MS365CredentialsForm } from '#/data/serviceCredentials/MS365CredentialsForm'
import { SnowflakeCredentialsForm } from '#/data/serviceCredentials/SnowflakeCredentialsForm'
import { StravaCredentialsForm } from '#/data/serviceCredentials/StravaCredentialsForm'
import type { CredentialInfo } from '#/data/serviceCredentials/types'
Expand All @@ -23,4 +24,10 @@ export const CREDENTIAL_INFOS: readonly [CredentialInfo, ...CredentialInfo[]] =
credentialType: 'strava',
form: StravaCredentialsForm,
},
{
icon: undefined,
nameId: 'ms365CredentialType',
credentialType: 'ms365',
form: MS365CredentialsForm,
},
]
55 changes: 55 additions & 0 deletions app/gui/src/dashboard/data/serviceCredentials/ms365.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* @file Definitions for the MS365 credentials integration.
*/
import invariant from 'tiny-invariant'

import type { MS365CredentialInput, SecretId } from '#/services/Backend'
import * as i18n from 'enso-common/src/text'
import { z } from 'zod'
import type { CredentialRecipe } from './types'
import { getOauthRedirectUri } from './utilities'

const EXTRA_SCOPES = ['openid', 'profile', 'offline_access']

export const FORM_SCHEMA = z.object({
name: z.string().min(1),
scopes: z.array(z.string()).refine((scopes) => scopes.length > 0, {
message: i18n.getText(i18n.resolveDictionary(), 'ms365CredentialScopesEmptyError'),
}),
})

/**
* The logic for submitting the MS365 credential form.
*/
export function submitForm(
createCredentials: (recipe: CredentialRecipe) => Promise<void>,
values: z.infer<typeof FORM_SCHEMA>,
): Promise<void> {
invariant($config.MS365_OAUTH_CLIENT_ID != null, 'MS365 OAuth client id is missing')
const ms365OauthClientId = $config.MS365_OAUTH_CLIENT_ID

const oauthScopes: string[] = [...EXTRA_SCOPES, ...values.scopes]
const input: MS365CredentialInput = {
type: 'MS365',
scopes: oauthScopes,
}
return createCredentials({
name: values.name,
input,
makeAuthUrl: (secretId: SecretId, nonce: string) => {
const state = btoa(JSON.stringify({ secretId, nonce }))
const scope = oauthScopes.join(' ')
const query = new URLSearchParams({
/* eslint-disable @typescript-eslint/naming-convention, camelcase */
client_id: ms365OauthClientId,
redirect_uri: getOauthRedirectUri('MS365'),
response_type: 'code',
response_mode: 'query',
state,
scope,
/* eslint-enable @typescript-eslint/naming-convention, camelcase */
})
return `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?${query.toString()}`
},
})
}
4 changes: 2 additions & 2 deletions build_tools/build/src/ci_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,10 @@ pub mod secret {
// === OAuth Integrations ===
/// The client ID for the Google OAuth integration used for Google Credentials.
pub const ENSO_IDE_GOOGLE_OAUTH_CLIENT_ID: &str = "ENSO_IDE_GOOGLE_OAUTH_CLIENT_ID";

// === OAuth Integrations ===
/// The client ID for the Strava OAuth integration used for Strava Credentials.
pub const ENSO_IDE_STRAVA_OAUTH_CLIENT_ID: &str = "ENSO_IDE_STRAVA_OAUTH_CLIENT_ID";
/// The client ID for the MS365 OAuth integration used for MS365 Credentials.
pub const ENSO_IDE_MS365_OAUTH_CLIENT_ID: &str = "ENSO_IDE_MS365_OAUTH_CLIENT_ID";
}

pub mod variables {
Expand Down
4 changes: 4 additions & 0 deletions build_tools/build/src/ci_gen/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ pub fn expose_gui_vars(step: Step) -> Step {
secret::ENSO_IDE_STRAVA_OAUTH_CLIENT_ID,
ide::web::env::ENSO_IDE_STRAVA_OAUTH_CLIENT_ID,
)
.with_secret_exposed_as(
secret::ENSO_IDE_MS365_OAUTH_CLIENT_ID,
ide::web::env::ENSO_IDE_MS365_OAUTH_CLIENT_ID,
)
}

/// Expose variables for debugging purposes.
Expand Down
3 changes: 3 additions & 0 deletions build_tools/build/src/ide/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ pub mod env {
/// The client ID for the Strava OAuth integration used for Strava Credentials.
ENSO_IDE_STRAVA_OAUTH_CLIENT_ID, String;

/// The client ID for the MS365 OAuth integration used for MS365 Credentials.
ENSO_IDE_MS365_OAUTH_CLIENT_ID, String;

ENSO_IDE_COMMIT_HASH, String;
ENSO_IDE_VERSION, String;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## Enso Signatures 1.0
## module Standard.Microsoft.Microsoft365
- type Microsoft365
- initialize credentials:Standard.Base.Any.Any -> Standard.Base.Any.Any
- list_root self -> Standard.Base.Any.Any
- to_js_object self -> Standard.Base.Any.Any
- user self -> Standard.Base.Any.Any
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export project.Azure_Storage.Azure_Storage

export project.Connection.SQLServer_Details.SQLServer_Details

export project.Microsoft365.Microsoft365
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from Standard.Base import all
from Standard.Base.Enso_Cloud.Enso_Secret import as_credential_reference

polyglot java import org.enso.base.enso_cloud.ExternalLibraryCredentialHelper.CredentialReference
polyglot java import org.enso.microsoft.ms365.MS365Service

type Microsoft365
## ---
private: true
---
private Service (ms365_service:MS365Service)

## ---
icon: cloud
---
Initializes the Microsoft365 instance using the given credentials file.

## Arguments:
- `credentials`: a Cloud secret or a file containing Microsoft365 credentials.
initialize : File|Enso_Secret -> Microsoft365
initialize credentials =
credentials_reference = as_credential_reference credentials
Microsoft365.Service (MS365Service.new credentials_reference)

## ---
icon: cloud
---

Fetches the profile of the current user.
user self =
_ms365_get self (_base_url + "/me")

## ---
icon: cloud
---

Lists the root directory of the user's OneDrive.
list_root self =
_ms365_get self (_base_url + "/me/drive/root/children")

## ---
private: true
---
to_js_object : JS_Object
to_js_object self =
JS_Object.from_pairs [["type", "MS365"]]

private _base_url = 'https://graph.microsoft.com/v1.0'

private _ms365_get ms365 url =
header = Header.authorization_bearer ms365.ms365_service.getAccessToken.token
HTTP.fetch url headers=[header] . decode_as_json
Original file line number Diff line number Diff line change
Expand Up @@ -171,5 +171,6 @@ public static RuntimeException malformedCredential() {
List.of(
new RestrictedAccess.AccessLocation(
"org.enso.google.GoogleOAuthHelper$CloudRenewableGoogleCredentials", "refresh"),
new RestrictedAccess.AccessLocation("org.enso.saas.strava.StravaService", "refresh"));
new RestrictedAccess.AccessLocation("org.enso.saas.strava.StravaService", "refresh"),
new RestrictedAccess.AccessLocation("org.enso.microsoft.ms365.MS365Service", "refresh"));
}
Loading
Loading