Skip to content

Commit

Permalink
Added Public TEST OAuth client for new users.
Browse files Browse the repository at this point in the history
  • Loading branch information
YukiGasai committed Oct 28, 2022
1 parent 030e766 commit a2edb63
Show file tree
Hide file tree
Showing 17 changed files with 356 additions and 160 deletions.
23 changes: 16 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,17 @@ Manage your Google Calendar from inside Obsidian

## Installation

- Download google-calendar from the latest [release](https://github.com/YukiGasai/obsidian-google-calendar/releases/)
- Extract zip into `.obsidian/plugins` folder
- Restart Obsidian
- Activate inside the obsidian settings page
- One click install from [comunity plugin store](obsidian://show-plugin?id=google-calendar)
- Go to settigns and activate plugin
- Go into plugin settings
- To *test* the plugin set `Use own authentication client` to false
- Press Login and authenticate with google


The function to use a public OAuth client is in beta and could be removed at any time.


### Create a own OAuth client (its easy)
- [Create Google Cloud Project](https://console.cloud.google.com/projectcreate?)
- [Activate Google Calendar API](https://console.cloud.google.com/marketplace/product/google/calendar-json.googleapis.com)
- [Configure OAUTH screen](https://console.cloud.google.com/apis/credentials/consent?)
Expand All @@ -29,11 +36,11 @@ Manage your Google Calendar from inside Obsidian
- select Webclient
- add `http://127.0.0.1:42813` as Javascript origin
- add `http://127.0.0.1:42813/callback` as redirect URI
- Switch on `Use own authentication client` in the settings tab
- add the keys into the fields under the plugin settings
- Press Login


### Using the plugin on Mobile (work around)
### Using the plugin on Mobile with own client (work around)

- Login on a desktop device
- Use the `Copy Google Refresh Token to Clipboard` command on that device
Expand Down Expand Up @@ -90,7 +97,7 @@ Refrence Google Calendar events inside text by typing @today or @01.01.2022 then
Other Options are @tomorrow, @yesterday, @+1 @-1

### CodeBlock
This plugin adds a cutom codeBlock gEvent to insert the Web, Month and day view inside file
This plugin adds a cutom codeBlock gEvent to insert the Web, Month and day and schedule view inside file. To options are parsed with yaml.

#### Parameters
```
Expand All @@ -101,6 +108,8 @@ This plugin adds a cutom codeBlock gEvent to insert the Web, Month and day view
height: number optional
navigation: boolean optional only for timeline view
timespan: number optional only for schedule view
include: [list of calendar ids or names]
exclude: [list of calendar ids or names]
```
```

Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "google-calendar",
"name": "Google Calendar",
"version": "1.5.1",
"version": "1.6.0",
"minAppVersion": "0.12.0",
"description": "Interact with your Google Calendar from Inside Obsidian",
"author": "YukiGasai",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "google-calendar",
"version": "1.5.1",
"version": "1.6.0",
"description": "Interact with your Google Calendar from Inside Obsidian",
"main": "main.js",
"scripts": {
Expand Down
21 changes: 20 additions & 1 deletion src/GoogleCalendarPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { MonthCalendarView, VIEW_TYPE_GOOGLE_CALENDAR_MONTH } from "./view/Month
import { WebCalendarView, VIEW_TYPE_GOOGLE_CALENDAR_WEB } from "./view/WebCalendarView";
import { ScheduleCalendarView, VIEW_TYPE_GOOGLE_CALENDAR_SCHEDULE } from "./view/ScheduleCalendarView";
import { checkEditorForAtDates } from "./helper/CheckEditorForAtDates";
import { getRefreshToken } from "./helper/LocalStorage";
import { getRefreshToken, setAccessToken, setExpirationTime, setRefreshToken, setToken } from "./helper/LocalStorage";
import { EventListModal } from './modal/EventListModal';
import { checkForEventNotes } from "./helper/AutoEventNoteCreator";
import { EventDetailsModal } from "./modal/EventDetailsModal";
Expand All @@ -24,11 +24,14 @@ import { GoogleCalendarPluginApi } from "./helper/GoogleCalendarPluginApi";




const DEFAULT_SETTINGS: GoogleCalendarPluginSettings = {
googleClientId: "",
googleClientSecret: "",
googleApiToken: "",
googleRefreshToken: "",
useCustomClient: true,
googleOAuthServer: "https://obsidian-google-calendar.vercel.app",
refreshInterval: 10,
showNotice: true,
autoCreateEventNotes: true,
Expand Down Expand Up @@ -345,6 +348,22 @@ export default class GoogleCalendarPlugin extends Plugin {
},
});


this.registerObsidianProtocolHandler("googleLogin", async (req) => {
if(this.settings.useCustomClient) return;

const refreshToken = req['rt'];
const accessToken = req['at'];
const expirationTime = req['et'];
const token = req['t'];
if(!refreshToken) return;
setRefreshToken(refreshToken);
setAccessToken(accessToken);
setExpirationTime(+new Date() + parseInt(expirationTime)*1000);
setToken(token);
new Notice("Login successfull!");
});

this.addSettingTab(new GoogleCalendarSettingTab(this.app, this));
}

Expand Down
84 changes: 64 additions & 20 deletions src/googleApi/GoogleAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ const PORT = 42813


function checkAccessTokenValid(): boolean {
//Check if the token exists
if(!getAccessToken() || getAccessToken() == "")return false;

//Check if Expiration time is not set or deafault 0
if(!getExpirationTime())return false;

Expand All @@ -42,6 +45,55 @@ function checkAccessTokenValid(): boolean {
return true;
}


const refreshWithCustomClient = async (plugin:GoogleCalendarPlugin): Promise<boolean> => {
const refreshBody = {
client_id: plugin.settings.googleClientId,
client_secret: plugin.settings.googleClientSecret,
grant_type: "refresh_token",
refresh_token: getRefreshToken(),
};

const response = await requestUrl({
method: "POST",
url: "https://oauth2.googleapis.com/token",
body: JSON.stringify(refreshBody)
});

if (response.status != 200) return false;

//Save new Access token and Expiration Time
const tokenData = await response.json;
setAccessToken(tokenData.access_token);
setExpirationTime(+new Date() + tokenData.expires_in*1000);
return true;
}


const refreshWithDefaultClient = async (plugin:GoogleCalendarPlugin): Promise<boolean> => {

const refreshBody = {
refresh_token: getRefreshToken(),
};

const response = await requestUrl({
url:`${plugin.settings.googleOAuthServer}/api/google/refresh`,
method: "POST",
body: JSON.stringify(refreshBody),
throw: true
});



if (response.status != 200) return false;

//Save new Access token and Expiration Time
const {tokenData} = await response.json;
setAccessToken(tokenData.access_token);
setExpirationTime(+new Date() + tokenData.expires_in*1000);
return true;
}

/**
* Function the get the acces token used in every request to the Google Calendar API
*
Expand All @@ -52,35 +104,27 @@ function checkAccessTokenValid(): boolean {
*/
export async function getGoogleAuthToken(): Promise<string> {
const plugin = GoogleCalendarPlugin.getInstance();
if (!settingsAreCompleteAndLoggedIn()) return;

if (!settingsAreCompleteAndLoggedIn()) return "";
let gotRefreshToken = false;
//Check if the Access token is still valid
if (
checkAccessTokenValid() == false
) {
//Acceess token is no loger valid have to create a new one
if (getRefreshToken() != "") {
const refreshBody = {
client_id: plugin.settings.googleClientId,
client_secret: plugin.settings.googleClientSecret,
grant_type: "refresh_token",
refresh_token: getRefreshToken(),
};

const response = await requestUrl({
url: "https://oauth2.googleapis.com/token",
method: "POST",
contentType: "application/json",
body: JSON.stringify(refreshBody)
});

//Save new Access token and Expiration Time
const tokenData = await response.json;
setAccessToken(tokenData.access_token);
setExpirationTime(+new Date() + tokenData.expires_in*1000);
if(plugin.settings.useCustomClient){

gotRefreshToken = await refreshWithCustomClient(plugin);

if(gotRefreshToken == false){
gotRefreshToken = await refreshWithDefaultClient(plugin)
}
}else{
gotRefreshToken = await refreshWithDefaultClient(plugin)
}
}
}

return getAccessToken();
}

Expand Down
13 changes: 10 additions & 3 deletions src/googleApi/GoogleColors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
*/

import type { GoogleEvent } from "../helper/types";
import GoogleCalendarPlugin from './../GoogleCalendarPlugin';
import {getToken} from "../helper/LocalStorage"
import { requestUrl } from 'obsidian';
import { settingsAreCompleteAndLoggedIn } from "../view/GoogleCalendarSettingTab";
import { createNotice } from "../helper/NoticeHelper";

const calendarColors = new Map<string, string>();
const eventColors = new Map<string, string>();
Expand All @@ -20,14 +22,19 @@ const eventColors = new Map<string, string>();
*/
export async function getGoogleColors():Promise<void> {

const plugin = GoogleCalendarPlugin.getInstance();
if(!settingsAreCompleteAndLoggedIn())return;

const response = await requestUrl({
url: `https://www.googleapis.com/calendar/v3/colors?key=${plugin.settings.googleApiToken}`,
url: `https://www.googleapis.com/calendar/v3/colors?key=${getToken()}`,
method: "GET",
contentType: "application/json",
})

if (response.status !== 200) {
createNotice("Could not load Google Colors");
return;
}

const colorData = response.json;

for (let i = 1; ; i++) {
Expand Down
32 changes: 17 additions & 15 deletions src/googleApi/GoogleCreateEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import type { GoogleEvent } from "../helper/types";

import { createNotice } from "../helper/NoticeHelper";
import { getGoogleAuthToken } from "../googleApi/GoogleAuth";
import GoogleCalendarPlugin from "../GoogleCalendarPlugin";
import { requestUrl } from 'obsidian';

import {getToken} from "../helper/LocalStorage"
import { settingsAreCompleteAndLoggedIn } from "../view/GoogleCalendarSettingTab";


/**
Expand All @@ -14,7 +14,8 @@ import { requestUrl } from 'obsidian';
* @returns The created Event
*/
export async function googleCreateEvent(event: GoogleEvent): Promise<GoogleEvent> {
const plugin = GoogleCalendarPlugin.getInstance();

if(!settingsAreCompleteAndLoggedIn())return null;

const calenderId = event.parent.id;

Expand All @@ -23,19 +24,20 @@ export async function googleCreateEvent(event: GoogleEvent): Promise<GoogleEvent

delete event.parent;

try {
const updateResponse = await requestUrl({
url: `https://www.googleapis.com/calendar/v3/calendars/${calenderId}/events?key=${plugin.settings.googleApiToken}`,
method: "POST",
headers: {"Authorization": "Bearer " + (await getGoogleAuthToken())},
body: JSON.stringify(event),
});

const createdEvent = await updateResponse.json;
const updateResponse = await requestUrl({
url: `https://www.googleapis.com/calendar/v3/calendars/${calenderId}/events?key=${getToken()}`,
method: "POST",
headers: {"Authorization": "Bearer " + (await getGoogleAuthToken())},
body: JSON.stringify(event),
});

return createdEvent;
} catch (error) {
createNotice("Could not create google event");
if (updateResponse.status !== 200) {
createNotice("Could not create Google Event");
return null;
}

const createdEvent = await updateResponse.json;

return createdEvent;

}
17 changes: 13 additions & 4 deletions src/googleApi/GoogleGetEvent.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
import { requestUrl } from "obsidian";
import { getGoogleAuthToken } from "./GoogleAuth";
import GoogleCalendarPlugin from "../GoogleCalendarPlugin";
import { settingsAreCompleteAndLoggedIn } from "../view/GoogleCalendarSettingTab";
import type { GoogleEvent } from "../helper/types";

import {getToken} from "../helper/LocalStorage"
import { createNotice } from "../helper/NoticeHelper";
/**
* Function to get information of a single event by id
* @param eventId The id of the event
* @param calendarId The id of the calendar the event is in
* @returns The found Event
*/
export async function googleGetEvent(eventId: string, calendarId?: string): Promise<GoogleEvent> {
const plugin = GoogleCalendarPlugin.getInstance();

if(!settingsAreCompleteAndLoggedIn())return null;

const updateResponse = await requestUrl({
url: `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/${eventId}?key=${plugin.settings.googleApiToken}`,
url: `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/${eventId}?key=${getToken()}`,
method: "GET",
headers: {"Authorization": "Bearer " + (await getGoogleAuthToken())},
});

if (updateResponse.status !== 200) {
createNotice("Could not get Google Event");
return null;
}


const createdEvent = await updateResponse.json;
return createdEvent;
}
Loading

0 comments on commit a2edb63

Please sign in to comment.