Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Commit 7b3a47e

Browse files
authored
Merge pull request #8 from microsoftgraph/feat/login
Login
2 parents daed1b1 + 24644a4 commit 7b3a47e

File tree

6,143 files changed

+245724
-114867
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

6,143 files changed

+245724
-114867
lines changed

.github/workflows/build-cli.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ jobs:
88
steps:
99
- name: Checkout
1010
uses: actions/checkout@v2
11+
with:
12+
submodules: true
1113
- name: Setup .NET Core SDK 6
1214
uses: actions/setup-dotnet@v1
1315
with:
1416
dotnet-version: 6.x
1517
- name: Add NuGet kiota source
16-
# TODO: Add NUGET_USER and NUGET_PASSWORD secrets
17-
# TODO: Add NUGET_URL to env
1818
# NOTE: Password encryption is not supported for the linux platform (Encryption is only supported on Windows platforms.)
1919
run: |
2020
dotnet nuget add source ${{env.NUGET_URL}} -n github -u ${{secrets.NUGET_USER}} -p ${{secrets.NUGET_PASSWORD}} --store-password-in-clear-text

.github/workflows/release-cli.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: "Release CLI"
2+
on: workflow_dispatch # Run manually. Incomplete workflow
3+
jobs:
4+
build-windows:
5+
runs-on: ubuntu-latest
6+
env:
7+
NUGET_URL: https://nuget.pkg.github.com/microsoft/index.json
8+
steps:
9+
- name: Checkout
10+
uses: actions/checkout@v2
11+
- name: Setup .NET Core SDK 6
12+
uses: actions/setup-dotnet@v1
13+
with:
14+
dotnet-version: 6.x
15+
- name: Add NuGet kiota source
16+
# NOTE: Password encryption is not supported for the linux platform (Encryption is only supported on Windows platforms.)
17+
run: |
18+
dotnet nuget add source ${{env.NUGET_URL}} -n github -u ${{secrets.NUGET_USER}} -p ${{secrets.NUGET_PASSWORD}} --store-password-in-clear-text
19+
- uses: actions/cache@v2
20+
with:
21+
path: ~/.nuget/packages
22+
# Look to see if there is a cache hit for the corresponding requirements file
23+
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
24+
restore-keys: |
25+
${{ runner.os }}-nuget
26+
- name: Install dependencies
27+
run: dotnet restore
28+
- name: Build
29+
run: dotnet publish --runtime win-x64 --self-contained true --configuration Release --no-restore
30+
build-mac:
31+
runs-on: ubuntu-latest
32+
env:
33+
NUGET_URL: https://nuget.pkg.github.com/microsoft/index.json
34+
steps:
35+
- name: Checkout
36+
uses: actions/checkout@v2
37+
- name: Setup .NET Core SDK 6
38+
uses: actions/setup-dotnet@v1
39+
with:
40+
dotnet-version: 6.x
41+
- name: Add NuGet kiota source
42+
# NOTE: Password encryption is not supported for the linux platform (Encryption is only supported on Windows platforms.)
43+
run: |
44+
dotnet nuget add source ${{env.NUGET_URL}} -n github -u ${{secrets.NUGET_USER}} -p ${{secrets.NUGET_PASSWORD}} --store-password-in-clear-text
45+
- uses: actions/cache@v2
46+
with:
47+
path: ~/.nuget/packages
48+
# Look to see if there is a cache hit for the corresponding requirements file
49+
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
50+
restore-keys: |
51+
${{ runner.os }}-nuget
52+
- name: Install dependencies
53+
run: dotnet restore
54+
- name: Build
55+
run: dotnet publish --runtime osx-x64 --self-contained true --configuration Release --no-restore

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ DocProject/Help/Html2
371371
DocProject/Help/html
372372

373373
# Click-Once directory
374-
publish/
374+
bin/**/publish/
375375

376376
# Publish Web Output
377377
*.[Pp]ublish.xml
@@ -571,3 +571,6 @@ FodyWeavers.xsd
571571
# Additional files built by Visual Studio
572572

573573
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,visualstudio,intellij+all,dotnetcore,windows,macos,linux
574+
575+
app-settings.*.json
576+
!app-settings.sample.json

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[submodule "msgraph-cli-core"]
2+
path = msgraph-cli-core
3+
url = https://github.com/microsoftgraph/msgraph-cli-core.git
4+
branch = main

.vscode/launch.json

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,38 @@
55
"version": "0.2.0",
66
"configurations": [
77
{
8-
"name": ".NET Core Launch (console)",
8+
"name": "help",
99
"type": "coreclr",
1010
"request": "launch",
1111
"preLaunchTask": "build",
12-
"program": "${workspaceFolder}/src/bin/Debug/net6.0/msgraph-cli.dll",
12+
"program": "${workspaceFolder}/src/bin/Debug/net6.0/mgc.dll",
1313
"args": ["-h"],
14-
"cwd": "${workspaceFolder}",
14+
"cwd": "${workspaceFolder}/src",
15+
"envFile": "${workspaceFolder}/src/.env",
16+
"console": "internalConsole",
17+
"stopAtEntry": false
18+
},
19+
{
20+
"name": "login",
21+
"type": "coreclr",
22+
"request": "launch",
23+
"preLaunchTask": "build",
24+
"program": "${workspaceFolder}/src/bin/Debug/net6.0/mgc.dll",
25+
"args": ["login", "--scopes", "User.ReadWrite Mail.ReadWrite"],
26+
"cwd": "${workspaceFolder}/src",
27+
"envFile": "${workspaceFolder}/src/.env",
28+
"console": "internalConsole",
29+
"stopAtEntry": false
30+
},
31+
{
32+
"name": "me get",
33+
"type": "coreclr",
34+
"request": "launch",
35+
"preLaunchTask": "build",
36+
"program": "${workspaceFolder}/src/bin/Debug/net6.0/mgc.dll",
37+
"args": ["me", "get"],
38+
"cwd": "${workspaceFolder}/src",
39+
"envFile": "${workspaceFolder}/src/.env",
1540
"console": "internalConsole",
1641
"stopAtEntry": false
1742
},

msgraph-cli-core

Submodule msgraph-cli-core added at 3d33676

src/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DOTNET_ENVIRONMENT=Development

src/Program.cs

Lines changed: 100 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,118 @@
11
using ApiSdk;
22
using Azure.Identity;
3-
using Microsoft.Graph.Cli.Utils;
3+
using Microsoft.Extensions.Configuration;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using Microsoft.Extensions.Hosting;
6+
using Microsoft.Graph.Cli.Core.Authentication;
7+
using Microsoft.Graph.Cli.Core.Commands.Authentication;
8+
using Microsoft.Graph.Cli.Core.Configuration;
9+
using Microsoft.Graph.Cli.Core.IO;
10+
using Microsoft.Graph.Cli.Core.Utils;
411
using Microsoft.Kiota.Authentication.Azure;
512
using Microsoft.Kiota.Http.HttpClientLibrary;
13+
using Microsoft.Kiota.Http.HttpClientLibrary.Middleware;
14+
using Microsoft.Kiota.Http.HttpClientLibrary.Middleware.Options;
615
using System.CommandLine;
16+
using System.CommandLine.Builder;
17+
using System.CommandLine.Hosting;
18+
using System.CommandLine.Parsing;
19+
using System.IO;
20+
using System.Linq;
21+
using System.Net.Http;
22+
using System.Reflection;
723
using System.Threading.Tasks;
24+
using System.Collections.Generic;
825

926
namespace Microsoft.Graph.Cli
1027
{
11-
class Program {
12-
static async Task<int> Main(string[] args) {
13-
DeviceCodeCredentialOptions credOptions = new()
14-
{
15-
ClientId = Constants.ClientId,
16-
TenantId = Constants.TenantId
17-
};
28+
class Program
29+
{
30+
const string SdkVersionHeaderValueFormatString = "{0}-cli/{1}.{2}.{3}";
31+
32+
static async Task<int> Main(string[] args)
33+
{
34+
// We don't have access to a built host yet. Get configuration settings using a configuration builder.
35+
// Required to set initial token credentials.
36+
var configBuilder = new ConfigurationBuilder();
37+
ConfigureAppConfiguration(configBuilder);
38+
var config = configBuilder.Build();
39+
40+
var authSettings = config.GetSection(Constants.AuthenticationSection).Get<AuthenticationOptions>();
41+
var authServiceFactory = new AuthenticationServiceFactory(new PathUtility());
42+
var authStrategy = AuthenticationStrategy.DeviceCode;
1843

19-
var credential = new DeviceCodeCredential(credOptions);
44+
var credential = await authServiceFactory.GetTokenCredentialAsync(authStrategy, authSettings?.TenantId, authSettings?.ClientId);
2045
var authProvider = new AzureIdentityAuthenticationProvider(credential);
21-
var core = new HttpClientRequestAdapter(authProvider);
46+
var defaultHandlers = KiotaClientFactory.CreateDefaultHandlers();
47+
48+
var assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version;
49+
var sdkVersionHeaderValue = string.Format(
50+
SdkVersionHeaderValueFormatString,
51+
"graph",
52+
assemblyVersion.Major,
53+
assemblyVersion.Minor,
54+
assemblyVersion.Build);
55+
56+
var telemetryHandlerOption = new TelemetryHandlerOption {
57+
TelemetryConfigurator = (request) => {
58+
request.Headers.Add("SdkVersion", sdkVersionHeaderValue);
59+
return request;
60+
}
61+
};
62+
var telemetryHandler = new TelemetryHandler(telemetryHandlerOption);
63+
defaultHandlers.Add(telemetryHandler);
64+
var finalHandler = KiotaClientFactory.ChainHandlersCollectionAndGetFirstLink(KiotaClientFactory.GetDefaultHttpMessageHandler(), defaultHandlers.ToArray());
65+
66+
using var httpClient = KiotaClientFactory.Create(finalHandler);
67+
var core = new HttpClientRequestAdapter(authProvider, httpClient: httpClient);
2268
var client = new GraphClient(core);
69+
var rootCommand = client.BuildCommand();
70+
rootCommand.Description = "Microsoft Graph CLI";
71+
72+
var commands = new List<Command>();
73+
var loginCommand = new LoginCommand(authServiceFactory);
74+
commands.Add(loginCommand.Build());
2375

76+
var logoutCommand = new LogoutCommand(new LogoutService());
77+
commands.Add(logoutCommand.Build());
78+
79+
var builder = BuildCommandLine(client, commands);
80+
81+
var parser = builder.UseHost(CreateHostBuilder).UseDefaults().Build();
82+
83+
return await parser.InvokeAsync(args);
84+
}
85+
86+
static CommandLineBuilder BuildCommandLine(GraphClient client, IEnumerable<Command> commands)
87+
{
2488
var rootCommand = client.BuildCommand();
2589
rootCommand.Description = "Microsoft Graph CLI";
26-
return await rootCommand.InvokeAsync(args);
90+
91+
foreach (var command in commands) {
92+
rootCommand.AddCommand(command);
93+
}
94+
95+
return new CommandLineBuilder(rootCommand);
96+
}
97+
98+
static IHostBuilder CreateHostBuilder(string[] args) =>
99+
Host.CreateDefaultBuilder().ConfigureHostConfiguration((configHost) => {
100+
configHost.SetBasePath(Directory.GetCurrentDirectory());
101+
}).ConfigureAppConfiguration((ctx, config) => {
102+
ConfigureAppConfiguration(config);
103+
}).ConfigureServices((ctx, services) => {
104+
var authSection = ctx.Configuration.GetSection(Constants.AuthenticationSection);
105+
services.Configure<AuthenticationOptions>(authSection);
106+
services.AddSingleton<IPathUtility, PathUtility>();
107+
});
108+
109+
static void ConfigureAppConfiguration(IConfigurationBuilder builder) {
110+
builder.Sources.Clear();
111+
builder.AddJsonFile("app-settings.json", optional: false);
112+
var dataDir = new PathUtility().GetApplicationDataDirectory();
113+
var userConfigPath = Path.Combine(dataDir, "settings.json");
114+
builder.AddJsonFile(userConfigPath, optional: true);
115+
builder.AddEnvironmentVariables(prefix: "MGC_");
27116
}
28117
}
29118
}

src/app-settings.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Warning"
5+
}
6+
}
7+
}

src/app-settings.sample.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"Authentication": {
3+
"ClientId": "client id",
4+
"TenantId": "tenant id"
5+
}
6+
}

0 commit comments

Comments
 (0)