Sync method

This commit is contained in:
Анатолий Копыл
2022-05-09 03:02:19 +03:00
parent b741964c3a
commit 7458750053
10 changed files with 126 additions and 21 deletions

6
backend/README.md Normal file
View File

@@ -0,0 +1,6 @@
# Worktime Backend
To start dev server:
```
$ denon dev
```

View File

@@ -0,0 +1,7 @@
export default async (ctx: any, next: Function) => {
const userId = await ctx.state.session.get('userId');
if (!userId) {
ctx.throw(403);
}
await next();
}

View File

@@ -3,7 +3,7 @@ import { Application } from "https://deno.land/x/oak@v10.5.1/mod.ts";
import { Session, CookieStore } from "https://deno.land/x/oak_sessions@v3.4.0/mod.ts";
import { oakCors } from "https://deno.land/x/cors@v1.2.2/mod.ts";
import routes from './routes/index.ts'
import routes from './routes.ts'
const PORT = Number(Deno.env.get('PORT'));
const SECRET = Deno.env.get('SECRET');

View File

@@ -0,0 +1,9 @@
export default class Error {
msg: string;
code: string;
constructor(msg: string, type: string, code: number) {
this.msg = msg;
this.code = `${type}-${code}`;
}
}

View File

@@ -10,18 +10,30 @@ export default class User {
constructor({
providerId,
authProvider
authProvider,
tasks,
categories,
updatedAt
}: {
providerId: string,
authProvider: string
authProvider: string,
tasks?: Array<Task>,
categories?: Array<string>,
updatedAt?: Date | string
}) {
this.providerId = providerId;
this.authProvider = authProvider;
this.id = `${providerId}@${authProvider}`;
this.tasks = [];
this.categories = [];
this.tasks = tasks ?? [];
this.categories = categories ?? [];
if (updatedAt instanceof Date) {
this.updatedAt = updatedAt;
} else if (updatedAt) {
this.updatedAt = new Date(updatedAt);
} else {
this.updatedAt = new Date();
}
}
addTask(task: Task) {
this.tasks.push(task);

View File

@@ -2,8 +2,9 @@ import "https://deno.land/x/dotenv@v3.2.0/load.ts";
import { Router } from "https://deno.land/x/oak@v10.5.1/mod.ts";
import { MongoClient } from "https://deno.land/x/mongo@v0.29.4/mod.ts";
import User from '../models/User.ts';
import getProviderId from '../getProviderId.ts';
import User from './models/User.ts';
import authorized from './authorized.ts';
import getProviderId from './getProviderId.ts';
const MONGODB_URI = String(Deno.env.get('MONGODB_URI'));
@@ -16,10 +17,21 @@ const users = db.collection<User>("users");
const endpoints = new Router()
.post("/login", async (ctx) => {
const body = await ctx.request.body({ type: "json" }).value;
const userId = await ctx.state.session.get('userId')
const token = body.token;
const authProvider = body.authProvider;
if (userId) {
ctx.response.body = 'success';
return
}
const providerId = await getProviderId(token, authProvider);
if (!providerId) {
ctx.response.status = 500
ctx.response.body = 'error';
return
}
let user = await users.findOne({
providerId,
@@ -38,6 +50,26 @@ const endpoints = new Router()
ctx.response.body = 'success';
})
.post('/sync', authorized, async (ctx) => {
const body = await ctx.request.body({ type: "json" }).value;
const userId = await ctx.state.session.get('userId')
const clientSideUser = new User(body.user);
const serverSideUser = await users.findOne({ id: userId })
if (!serverSideUser) {
ctx.response.status = 500
ctx.response.body = 'error';
return
}
if (serverSideUser.updatedAt <= clientSideUser.updatedAt) {
serverSideUser.tasks = clientSideUser.tasks;
serverSideUser.categories = clientSideUser.categories;
serverSideUser.updatedAt = new Date();
}
ctx.response.body = serverSideUser;
})
const routes = new Router()
.use("/api", endpoints.routes(), endpoints.allowedMethods())

View File

@@ -4,6 +4,16 @@
<div id="modalSpot" />
</template>
<script>
import api from '@/api';
export default {
async mounted() {
await api.sync();
},
};
</script>
<style lang="scss">
@import "@/scss/style.scss";

36
frontend/src/api/index.js Normal file
View File

@@ -0,0 +1,36 @@
import store from '@/store';
class Api {
baseUrl = 'http://localhost:3000/api';
async login(token, authProvider) {
const response = await fetch(`${this.baseUrl}/login`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify({
token,
authProvider,
}),
});
console.log(await response.json());
}
async sync() {
const { tasks, categories, updatedAt } = store.state;
const response = await fetch(`${this.baseUrl}/sync`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify({
user: {
tasks,
categories,
updatedAt,
},
}),
});
console.log(await response.json());
}
}
export default new Api();

View File

@@ -11,7 +11,7 @@ export default createStore({
tasks: [],
midnightReset: false,
lastReset: new Date(),
token: null,
updatedAt: new Date(),
darkTheme: true,
},
mutations: {
@@ -96,8 +96,8 @@ export default createStore({
state.midnightReset = !!value;
},
setToken(state, token) {
state.token = token;
updated(state) {
state.updatedAt = new Date();
},
},
plugins: [vuexLocal.plugin],

View File

@@ -5,21 +5,14 @@
</template>
<script>
import api from '@/api';
export default {
async mounted() {
const baseUrl = 'http://localhost:3000/api/login';
const token = /access_token=([^&]+)/.exec(this.$route.hash)[1];
const authProvider = /state=([^&]+)/.exec(this.$route.hash)[1];
const response = await fetch(baseUrl, {
method: 'POST',
credentials: 'include',
body: JSON.stringify({
token,
authProvider,
}),
});
console.log(await response.json());
api.login(token, authProvider);
},
};
</script>