完成权限的验证
This commit is contained in:
parent
f7d99047d4
commit
78b7dd36c2
|
|
@ -35,3 +35,4 @@ app/
|
|||
|
||||
config.development.js
|
||||
adapter.development.js
|
||||
package-lock.json
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -11,14 +11,15 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"think-cache": "^1.0.0",
|
||||
"think-session": "^1.0.0",
|
||||
"think-cache-file": "^1.0.8",
|
||||
"think-logger3": "^1.0.0",
|
||||
"think-model": "^1.0.0",
|
||||
"think-model-mysql": "^1.0.0",
|
||||
"think-session": "^1.0.0",
|
||||
"think-session-file": "^1.0.5",
|
||||
"think-session-jwt": "^1.1.1",
|
||||
"think-view": "^1.0.0",
|
||||
"think-view-nunjucks": "^1.0.1",
|
||||
"think-model-mysql": "^1.0.0",
|
||||
"think-logger3": "^1.0.0",
|
||||
"thinkjs": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
-- 用户信息表
|
||||
drop table if exists users;
|
||||
CREATE TABLE `users` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id
|
||||
`username` varchar(255) NOT NULL, -- 用户名
|
||||
`password` varchar(255) NOT NULL, -- 密码
|
||||
`email` varchar(255) NOT NULL, -- 邮箱
|
||||
`created_at` datetime DEFAULT now(), -- 创建时间
|
||||
`last_login` datetime DEFAULT NULL, -- 最后一次登录时间
|
||||
`search_history` varchar(512) DEFAULT NULL, -- 历史搜索记录
|
||||
`avatar` varchar(512) DEFAULT NULL, -- 头像地址
|
||||
`quick_url` varchar(2048) DEFAULT '{\"B\":\"https://www.baidu.com/\",\"G\":\"https://www.google.com.hk/\",\"V\":\"https://www.v2ex.com/\",\"L\":\"http://luchenqun.com/\",\"H\":\"https://github.com/\",\"Q\":\"http://www.iqiyi.com/\",\"J\":\"https://www.jd.com/\"}', -- 全局快捷地址
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `username` (`username`),
|
||||
UNIQUE KEY `email` (`email`)
|
||||
);
|
||||
|
||||
-- 书签表
|
||||
drop table if exists bookmarks;
|
||||
CREATE TABLE `bookmarks` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id
|
||||
`user_id` int(11) NOT NULL, -- 用户id
|
||||
`tag_id` int(11) NOT NULL, -- 分类id (只允许一个书签对应一个分类)
|
||||
`title` varchar(255) NOT NULL, -- 标题
|
||||
`description` varchar(4096) DEFAULT NULL, -- 描述
|
||||
`url` varchar(1024) NOT NULL, -- 链接
|
||||
`public` tinyint(4) DEFAULT '0', -- 是否公开 1 公开,0 不公开
|
||||
`click_count` smallint DEFAULT 1, -- 总共点击次数
|
||||
`created_at` datetime DEFAULT now(), -- 创建时间
|
||||
`last_click` datetime DEFAULT now(), -- 最后一次点击时间
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `userIdIdx` (`user_id`)
|
||||
);
|
||||
|
||||
-- 书签分类表
|
||||
drop table if exists tags;
|
||||
CREATE TABLE `tags` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id
|
||||
`user_id` int(11) NOT NULL, -- 用户id
|
||||
`name` varchar(32) NOT NULL, -- 标签
|
||||
`last_use` datetime DEFAULT now(), -- 最后使用标签的时间
|
||||
`sort` tinyint(8) DEFAULT 0, -- 书签排序
|
||||
`show` tinyint(8) DEFAULT 1, -- 书签是否显示
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `userIdIdx` (`user_id`)
|
||||
);
|
||||
|
||||
-- 建议留言
|
||||
drop table if exists advices;
|
||||
CREATE TABLE `advices` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id
|
||||
`user_id` int(11) NOT NULL, -- 用户id
|
||||
`comment` text NOT NULL, -- 评论
|
||||
`created_at` datetime DEFAULT now(), -- 创建时间
|
||||
`state` tinyint(4) DEFAULT '0', -- 处理结果
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `userIdIdx` (`user_id`)
|
||||
);
|
||||
|
||||
-- 书签表
|
||||
drop table if exists hot_bookmarks;
|
||||
CREATE TABLE `hot_bookmarks` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id(articleId)
|
||||
`date` int(11) NOT NULL DEFAULT 0, -- 日期(自己添加)
|
||||
`title` varchar(255) DEFAULT NULL, -- 标题(title)
|
||||
`description` varchar(4096) DEFAULT NULL, -- 描述(自己添加)
|
||||
`url` varchar(1024) DEFAULT NULL, -- 链接(url)
|
||||
`fav_count` smallint DEFAULT 1, -- 总共收藏人数(favCount)
|
||||
`created_by` varchar(64) DEFAULT NULL, -- 创建者(sourceName)
|
||||
`created_at` bigint DEFAULT 0, -- 创建时间(updatetime)
|
||||
`last_click` bigint DEFAULT 0, -- 最后一次点击时间(createtime)
|
||||
`snap_url` varchar(1024) DEFAULT NULL, -- 截图链接(imageList[0])
|
||||
`favicon_url` varchar(1024) DEFAULT NULL, -- icon链接(sourceLogo)
|
||||
`status` tinyint(4) DEFAULT '0', -- 状态
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
-- 备忘录
|
||||
drop table if exists notes;
|
||||
CREATE TABLE `notes` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id
|
||||
`user_id` int(11) NOT NULL, -- 用户id
|
||||
`content` text NOT NULL, -- 备忘内容
|
||||
`tag_id` int(11) NOT NULL, -- 分类id
|
||||
`created_at` datetime DEFAULT now(), -- 创建时间
|
||||
`public` tinyint(4) DEFAULT '0', -- 是否公开 1 公开,0 不公开
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
const fileCache = require('think-cache-file');
|
||||
const nunjucks = require('think-view-nunjucks');
|
||||
const fileSession = require('think-session-file');
|
||||
const JWTSession = require('think-session-jwt');
|
||||
const mysql = require('think-model-mysql');
|
||||
const {Console, File, DateFile} = require('think-logger3');
|
||||
const path = require('path');
|
||||
|
|
@ -52,19 +52,27 @@ exports.model = {
|
|||
* @type {Object}
|
||||
*/
|
||||
exports.session = {
|
||||
type: 'file',
|
||||
type: 'jwt',
|
||||
common: {
|
||||
cookie: {
|
||||
name: 'mybookmark'
|
||||
// keys: ['werwer', 'werwer'],
|
||||
// signed: true
|
||||
name: 'thinkjs',
|
||||
}
|
||||
},
|
||||
file: {
|
||||
handle: fileSession,
|
||||
sessionPath: path.join(think.ROOT_PATH, 'runtime/session')
|
||||
jwt: {
|
||||
handle: JWTSession,
|
||||
secret: 'secret', // secret is reqired
|
||||
tokenType: 'header', // ['query', 'body', 'header', 'cookie'], 'cookie' is default
|
||||
tokenName: 'authorization', // if tokenType not 'cookie', this will be token name, 'jwt' is default 后端字母要小写
|
||||
sign: {
|
||||
// sign options is not required
|
||||
expiresIn: '604800s' // 7天过期
|
||||
},
|
||||
verify: {
|
||||
// verify options is not required
|
||||
},
|
||||
verifyCallback: (error) => { throw new Error("token verify error"); }, // default verify fail callback
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* view adapter config
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
// default config
|
||||
module.exports = {
|
||||
workers: 1
|
||||
workers: 1,
|
||||
errnoField: 'code',
|
||||
errmsgField: 'msg'
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,17 +7,19 @@ function md5(str) {
|
|||
|
||||
module.exports = class extends Base {
|
||||
async __before() {
|
||||
let user = await this.session('user');
|
||||
user = {}
|
||||
console.log("session user", user);
|
||||
|
||||
if (['register', 'login'].indexOf(this.ctx.action) >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取用户的 session 信息,如果为空,返回 false 阻止后续的行为继续执行
|
||||
if (think.isEmpty(user)) {
|
||||
return this.fail('NOT_LOGIN');
|
||||
try {
|
||||
let user = await this.session('user');
|
||||
console.log(".......session user", this.ctx.action, Object.keys(user));
|
||||
if (think.isEmpty(user)) {
|
||||
return this.fail(401, '请先登录');
|
||||
}
|
||||
this.ctx.state.user = user;
|
||||
} catch (error) {
|
||||
// 获取用户的 session 信息,如果为空,返回 false 阻止后续的行为继续执行
|
||||
return this.fail(401, '请先登录:' + error.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,20 +50,40 @@ module.exports = class extends Base {
|
|||
if (think.isEmpty(data)) {
|
||||
this.json({ code: 2, msg: "账号或者密码错误" });
|
||||
} else {
|
||||
delete data.password;
|
||||
const token = await this.session('user', {
|
||||
id: data.id,
|
||||
username: data.username
|
||||
});
|
||||
data.token = token;
|
||||
this.json({ code: 0, data, msg: "登陆成功" });
|
||||
data.password = "******";
|
||||
await this.session('user', data); // @todo 对session的maxAge进行操作(目前默认永久不过期)
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
this.json({ code: 1, data: '', msg: error.toString() });
|
||||
}
|
||||
}
|
||||
|
||||
async userInfoAction() {
|
||||
this.json({ code: 1, data: '', msg: '' });
|
||||
// 通过session获取自己信息
|
||||
async ownAction() {
|
||||
let full = this.post().full;
|
||||
if (full) {
|
||||
let data = await this.model('users').where({ id: this.ctx.state.user.id }).find();
|
||||
delete data.password;
|
||||
this.json({ code: 0, data, msg: '' });
|
||||
} else {
|
||||
this.json({ code: 0, data: this.ctx.state.user, msg: '' });
|
||||
}
|
||||
}
|
||||
|
||||
autoLoginAction() {
|
||||
this.json({ "succ": true });
|
||||
async tagsAction() {
|
||||
let tags = await this.model('tags').where({ user_id: this.ctx.state.user.id }).order('sort ASC, last_use DESC').select();
|
||||
for (let tag of tags) {
|
||||
let cnt = await this.model('tags_bookmarks').where({ tag_id: tag.id }).count();
|
||||
let ncnt = await this.model('notes').where({ tag_id: tag.id }).count();
|
||||
tag.cnt = cnt;
|
||||
tag.ncnt = ncnt;
|
||||
}
|
||||
this.json({ code: 0, data: tags, msg: '' });
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,17 +1,26 @@
|
|||
var app = angular.module('bookmarkApp', ['ui.router', 'ngCookies', 'infinite-scroll', 'angular-sortable-view', 'ngDialog']);
|
||||
|
||||
axios.defaults.baseURL = '/api/';
|
||||
axios.defaults.headers.common['Authorization'] = localStorage.getItem("authorization");
|
||||
|
||||
// 添加响应拦截器
|
||||
axios.interceptors.response.use(function (response) {
|
||||
let data = response.data;
|
||||
if (data.code === 0) {
|
||||
if (data.msg) {
|
||||
toastr.success(data.msg, "提示");
|
||||
let reply = response.data;
|
||||
if (reply.code === 0) {
|
||||
if (reply.msg) {
|
||||
toastr.success(reply.msg, "提示");
|
||||
}
|
||||
return Promise.resolve(data.data);
|
||||
return Promise.resolve(reply.data);
|
||||
} else {
|
||||
toastr.error(`错误信息:${data.msg}(错误码:${data.code})`, '请求错误');
|
||||
return Promise.reject(data);
|
||||
toastr.error(`错误信息:${reply.msg}(错误码:${reply.code})`, '请求错误');
|
||||
if (reply.code == 401) {
|
||||
let hash = document.location.hash;
|
||||
let origin = document.location.origin;
|
||||
if (!(hash == "#/login" || hash == "#/")) {
|
||||
window.location.href = `${origin}/#/login`;
|
||||
}
|
||||
}
|
||||
return Promise.reject(reply);
|
||||
}
|
||||
}, function (error) {
|
||||
toastr.error(`错误信息:${error.toString()}`, '网络错误');
|
||||
|
|
|
|||
|
|
@ -11,13 +11,7 @@ app.controller('adviceCtr', ['$scope', '$state', '$timeout', 'bookmarkService',
|
|||
$scope.category = ["功能", "BUG", "其他"];
|
||||
$scope.user = {};
|
||||
|
||||
bookmarkService.userInfo({})
|
||||
.then((data) => {
|
||||
$scope.user = data;
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
});
|
||||
axios.get('own', {}).then(user => $scope.user = user);
|
||||
|
||||
$scope.ok = function () {
|
||||
if ($scope.comment == '') {
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ app.controller('bookmarksCtr', ['$scope', '$state', '$stateParams', '$filter', '
|
|||
})
|
||||
});
|
||||
|
||||
function getBookmarks() {
|
||||
async function getBookmarks() {
|
||||
var params = {}
|
||||
params.showStyle = $scope.showStyle
|
||||
params.currentPage = $scope.currentPage;
|
||||
|
|
|
|||
|
|
@ -4,35 +4,18 @@ app.controller('homeCtr', ['$scope', '$stateParams', '$filter', '$state', '$wind
|
|||
$window.location = "http://m.mybookmark.cn/#/tags";
|
||||
return;
|
||||
}
|
||||
bookmarkService.autoLogin()
|
||||
.then((data) => {
|
||||
if (data.logined) {
|
||||
pubSubService.publish('loginCtr.login', {
|
||||
'login': data.logined,
|
||||
});
|
||||
$state.go('tags');
|
||||
toastr.success('自动登陆成功,系统将自动跳转到书签分类页面', "提示");
|
||||
} else {
|
||||
console.log('autoLogin failed......................')
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: false,
|
||||
index: dataService.NotLoginIndexHome
|
||||
});
|
||||
transition();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('autoLogin err', err);
|
||||
transition();
|
||||
});
|
||||
$('.js-segment-home').transition('hide');
|
||||
|
||||
function transition() {
|
||||
var className = 'js-segment-home';
|
||||
$('.' + className).transition('hide');
|
||||
$('.' + className).transition({
|
||||
animation: dataService.animation(),
|
||||
duration: 500,
|
||||
});
|
||||
}
|
||||
(async () => {
|
||||
try {
|
||||
await axios.get('own', {});
|
||||
pubSubService.publish('loginCtr.login', { 'login': true });
|
||||
$state.go('tags');
|
||||
} catch (error) {
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: false,
|
||||
index: dataService.NotLoginIndexHome
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
}]);
|
||||
|
|
|
|||
|
|
@ -38,10 +38,12 @@ app.controller('loginCtr', ['$scope', '$filter', '$state', '$http', '$cookieStor
|
|||
};
|
||||
$cookieStore.put("username", $scope.username);
|
||||
|
||||
await axios.post('login', params);
|
||||
return;
|
||||
let data = await axios.post('login', params);
|
||||
axios.defaults.headers.common['Authorization'] = data.token;
|
||||
localStorage.setItem("authorization", data.token);
|
||||
|
||||
pubSubService.publish('loginCtr.login', { login: true });
|
||||
$state.go('bookmarks', {})
|
||||
$state.go('tags')
|
||||
}
|
||||
|
||||
$scope.showRegister = async function () {
|
||||
|
|
|
|||
|
|
@ -26,16 +26,12 @@ app.controller('menuCtr', ['$scope', '$stateParams', '$state', '$window', '$time
|
|||
$scope.loginMenus = dataService.loginMenus; // 登陆之后显示的菜单数据。uiSerf:内部跳转链接。
|
||||
$scope.notLoginMenus = dataService.notLoginMenus; // 未登陆显示的菜单数据
|
||||
|
||||
bookmarkService.userInfo({})
|
||||
.then((data) => {
|
||||
$scope.user = data;
|
||||
if (data.username === 'lcq') {
|
||||
$scope.loginMenus[dataService.LoginIndexHot].show = false;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
});
|
||||
(async () => {
|
||||
$scope.user = await axios.get('own', {});
|
||||
if (data.username === 'lcq') {
|
||||
$scope.loginMenus[dataService.LoginIndexHot].show = false;
|
||||
}
|
||||
})();
|
||||
|
||||
$scope.toggleReady = function (ready) {
|
||||
if (ready) {
|
||||
|
|
@ -248,29 +244,23 @@ app.controller('menuCtr', ['$scope', '$stateParams', '$state', '$window', '$time
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
bookmarkService.userInfo({})
|
||||
.then((user) => {
|
||||
$scope.searchHistory = JSON.parse(user.search_history || '[]');
|
||||
$scope.quickUrl = JSON.parse(user.quick_url || '{}');
|
||||
$scope.searchHistory.forEach((item, index) => {
|
||||
$scope.searchIcon(item)
|
||||
})
|
||||
$timeout(function () {
|
||||
var showStyle = (user && user.show_style) || 'navigate';
|
||||
if (showStyle) {
|
||||
$('.js-bookmark-dropdown' + ' .radio.checkbox').checkbox('set unchecked');
|
||||
$('.js-radio-' + showStyle).checkbox('set checked');
|
||||
$('.js-bookmark-dropdown' + ' .field.item').removeClass('active selected');
|
||||
$('.js-field-' + showStyle).addClass('active selected');
|
||||
}
|
||||
}, 1000)
|
||||
(async () => {
|
||||
let user = await axios.get('own', { full: true });
|
||||
$scope.searchHistory = JSON.parse(user.search_history || '[]');
|
||||
$scope.quickUrl = JSON.parse(user.quick_url || '{}');
|
||||
$scope.searchHistory.forEach((item, index) => {
|
||||
$scope.searchIcon(item)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
// toastr.error('获取信息失败。错误信息:' + JSON.stringify(err), "错误");
|
||||
});
|
||||
$timeout(function () {
|
||||
var showStyle = (user && user.show_style) || 'navigate';
|
||||
if (showStyle) {
|
||||
$('.js-bookmark-dropdown' + ' .radio.checkbox').checkbox('set unchecked');
|
||||
$('.js-radio-' + showStyle).checkbox('set checked');
|
||||
$('.js-bookmark-dropdown' + ' .field.item').removeClass('active selected');
|
||||
$('.js-field-' + showStyle).addClass('active selected');
|
||||
}
|
||||
}, 1000)
|
||||
})();
|
||||
|
||||
$timeout(function () {
|
||||
$('.suggest')
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ app.controller('tagsCtr', ['$scope', '$filter', '$state', '$window', '$statePara
|
|||
return;
|
||||
}
|
||||
|
||||
getTags({});
|
||||
(async () => {
|
||||
await getTags();
|
||||
})()
|
||||
|
||||
// getTags({});
|
||||
|
||||
var perPageItems = 20;
|
||||
var dialog = null;
|
||||
|
|
@ -486,8 +490,10 @@ app.controller('tagsCtr', ['$scope', '$filter', '$state', '$window', '$statePara
|
|||
})
|
||||
});
|
||||
|
||||
function getTags(params) {
|
||||
async function getTags(params) {
|
||||
$scope.loadTags = true;
|
||||
$scope.tags = await axios.get('tags');
|
||||
return;
|
||||
bookmarkService.getTags(params)
|
||||
.then((data) => {
|
||||
$scope.tags = []
|
||||
|
|
|
|||
Loading…
Reference in New Issue