Toggle navigation
Toggle navigation
This project
Loading...
Sign in
2021-1-capstone-design1
/
RIT_Project1
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
1
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
박권수
2021-10-04 19:36:12 +0900
Browse Files
Options
Browse Files
Download
Plain Diff
Commit
6918915f28ca6fd3129e544cdd8c2cb5c67fa0fb
6918915f
2 parents
7bd1e1cc
319c4253
Merge branch 'server' into web
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
244 additions
and
37 deletions
server/package-lock.json
server/package.json
server/src/api/auth/auth.ctrl.js
server/src/api/auth/index.js
server/src/api/doctor/doctor.ctrl.js
server/src/lib/jwtMiddleWare.js
server/src/models/user.js
server/src/util/Batch.js
server/src/util/DataProcess.js
server/src/util/FCM.js
server/yarn.lock
server/package-lock.json
View file @
6918915
...
...
@@ -12,6 +12,7 @@
"@google-cloud/storage"
:
"^5.14.2"
,
"@koa/cors"
:
"^3.1.0"
,
"firebase-admin"
:
"^9.11.1"
,
"google-auth-library"
:
"^7.10.0"
,
"koa-body"
:
"^4.2.0"
,
"moment"
:
"^2.29.1"
,
"moment-timezone"
:
"^0.5.33"
,
...
...
@@ -1835,9 +1836,9 @@
}
},
"node_modules/google-auth-library"
:
{
"version"
:
"7.
9.2
"
,
"resolved"
:
"https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.
9.2
.tgz"
,
"integrity"
:
"sha512-
HjxbJt660a+YUTYAgYor87JCuBZvjUSNBExk4bXTEaMuCn8IHSDeHmFxKqThuDPrLCiKJp8blk/Ze8f7SI4N6g
=="
,
"version"
:
"7.
10.0
"
,
"resolved"
:
"https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.
10.0
.tgz"
,
"integrity"
:
"sha512-
ICsqaU+lxMHVlDUzMrfVIEqnARw2AwBiZ/2KnNM6BcTf9Nott+Af87DTIzmlnW865p3REUP2MVL0xkPC3a61aQ
=="
,
"dependencies"
:
{
"arrify"
:
"^2.0.0"
,
"base64-js"
:
"^1.3.0"
,
...
...
@@ -5277,9 +5278,9 @@
}
},
"google-auth-library"
:
{
"version"
:
"7.
9.2
"
,
"resolved"
:
"https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.
9.2
.tgz"
,
"integrity"
:
"sha512-
HjxbJt660a+YUTYAgYor87JCuBZvjUSNBExk4bXTEaMuCn8IHSDeHmFxKqThuDPrLCiKJp8blk/Ze8f7SI4N6g
=="
,
"version"
:
"7.
10.0
"
,
"resolved"
:
"https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.
10.0
.tgz"
,
"integrity"
:
"sha512-
ICsqaU+lxMHVlDUzMrfVIEqnARw2AwBiZ/2KnNM6BcTf9Nott+Af87DTIzmlnW865p3REUP2MVL0xkPC3a61aQ
=="
,
"requires"
:
{
"arrify"
:
"^2.0.0"
,
"base64-js"
:
"^1.3.0"
,
...
...
server/package.json
View file @
6918915
...
...
@@ -20,6 +20,7 @@
"@google-cloud/storage"
:
"^5.14.2"
,
"@koa/cors"
:
"^3.1.0"
,
"firebase-admin"
:
"^9.11.1"
,
"google-auth-library"
:
"^7.10.0"
,
"koa-body"
:
"^4.2.0"
,
"moment"
:
"^2.29.1"
,
"moment-timezone"
:
"^0.5.33"
,
...
...
server/src/api/auth/auth.ctrl.js
View file @
6918915
...
...
@@ -93,6 +93,7 @@ exports.searchHospital = async ctx => {
};
};
//의사 회원가입
exports
.
doctorRegister
=
async
ctx
=>
{
const
{
userId
,
...
...
@@ -193,6 +194,7 @@ exports.doctorRegister = async ctx => {
}
//로컬 로그인
exports
.
login
=
async
(
ctx
)
=>
{
const
{
userId
,
password
,
deviceToken
}
=
ctx
.
request
.
body
;
...
...
@@ -211,7 +213,7 @@ exports.login = async(ctx) => {
}
const
user
=
await
User
.
findByUserId
(
userId
);
if
(
!
user
||
!
user
.
userTypeCd
)
{
if
(
!
user
||
!
user
.
userTypeCd
||
user
.
authTypeCd
!==
'NORMAL'
)
{
ctx
.
status
=
401
;
ctx
.
body
=
{
error
:
'존재하지 않는 회원입니다.'
,
...
...
@@ -259,6 +261,180 @@ exports.login = async(ctx) => {
};
//social Register
exports
.
socialRegister
=
async
ctx
=>
{
const
{
socialType
}
=
ctx
.
params
;
const
{
accessToken
,
deviceToken
}
=
ctx
.
request
.
body
;
const
verifyingToken
=
socialType
.
toUpperCase
()
===
'GOOGLE'
?
async
()
=>
{
//id_token
const
result
=
jwt
.
decode
(
accessToken
);
return
{
userId
:
result
.
email
,
userNm
:
result
.
name
,
contact
:
null
,
birth
:
null
,
};
}
:
socialType
.
toUpperCase
()
===
'NAVER'
?
async
()
=>
{
const
url
=
'https://openapi.naver.com/v1/nid/me'
;
const
result
=
await
axios
.
get
(
url
,
{
headers
:
{
Authorization
:
`Bearer
${
accessToken
}
`
,
},
});
const
{
email
,
mobile
,
name
,
birthday
,
birthyear
}
=
result
.
data
.
response
;
return
{
userId
:
email
,
userNm
:
name
,
contact
:
mobile
,
birth
:
`
${
birthyear
}
-
${
birthday
}
`
,
};
}
:
socialType
.
toUpperCase
()
===
'KAKAO'
?
async
()
=>
{
const
url
=
'https://kapi.kakao.com/v2/user/me'
;
const
result
=
await
axios
.
get
(
url
,
{
headers
:
{
Authorization
:
`Bearer
${
accessToken
}
`
,
},
});
console
.
log
(
result
);
return
result
;
}
:
()
=>
null
;
const
verifyingInfo
=
await
verifyingToken
();
if
(
!
verifyingInfo
||
!
verifyingInfo
.
userId
)
{
ctx
.
status
=
403
;
ctx
.
body
=
{
error
:
'잘못된 요청'
,
};
return
;
}
const
{
userId
,
userNm
,
birth
,
contact
}
=
verifyingInfo
;
const
existUser
=
await
User
.
findByUserId
(
userId
);
if
(
existUser
)
{
ctx
.
status
=
409
;
ctx
.
body
=
{
error
:
'이미 가입된 회원'
,
};
return
;
}
const
user
=
new
User
({
userId
,
hashedPassword
:
null
,
authTypeCd
:
socialType
.
toUpperCase
(),
useYn
:
'Y'
,
});
const
profile
=
new
Profile
({
userId
,
userNm
,
birth
,
contact
,
deviceToken
,
});
await
user
.
save
();
await
profile
.
save
();
ctx
.
status
=
201
;
};
//social Login
exports
.
socialLogin
=
async
ctx
=>
{
const
{
socialType
}
=
ctx
.
params
;
const
{
accessToken
,
deviceToken
,
}
=
ctx
.
request
.
body
;
const
verifyingToken
=
socialType
.
toUpperCase
()
===
'GOOGLE'
?
async
()
=>
{
//id_token : google Login
const
result
=
jwt
.
decode
(
accessToken
);
return
result
.
email
;
}
:
socialType
.
toUpperCase
()
===
'NAVER'
?
async
()
=>
{
//naver Login
const
url
=
'https://openapi.naver.com/v1/nid/me'
;
const
result
=
await
axios
.
get
(
url
,
{
headers
:
{
Authorization
:
`Bearer
${
accessToken
}
`
,
},
});
return
result
.
data
.
response
.
email
;
}
:
socialType
.
toUpperCase
()
===
'KAKAO'
?
async
()
=>
{
//kakao Login
const
url
=
'https://kapi.kakao.com/v2/user/me'
;
const
result
=
await
axios
.
get
(
url
,
{
headers
:
{
Authorization
:
`Bearer
${
accessToken
}
`
,
},
});
console
.
log
(
result
);
return
result
;
}
:
()
=>
null
;
const
userId
=
await
verifyingToken
();
if
(
!
userId
)
{
ctx
.
status
=
403
;
ctx
.
body
=
{
error
:
'잘못된 요청입니다'
,
};
return
;
}
const
user
=
await
User
.
findByUserId
(
userId
);
if
(
!
user
||
user
.
useYn
!==
'Y'
)
{
ctx
.
status
=
404
;
ctx
.
body
=
{
error
:
'존재하지 않는 회원입니다.'
,
};
return
;
}
else
if
(
user
.
authTypeCd
!==
socialType
.
toUpperCase
())
{
ctx
.
status
=
400
;
ctx
.
body
=
{
error
:
'잘못된 소셜 로그인입니다.'
,
};
return
;
}
const
profile
=
await
Profile
.
findOne
({
userId
});
if
(
profile
.
deviceToken
!==
deviceToken
)
{
profile
.
updateDeviceToken
(
deviceToken
);
await
profile
.
save
();
}
const
token
=
await
user
.
generateToken
();
ctx
.
status
=
200
;
ctx
.
body
=
{
userTypeCd
:
user
.
userTypeCd
,
token
,
};
};
exports
.
logout
=
async
(
ctx
)
=>
{
ctx
.
cookies
.
set
(
'access_token'
,
null
,
{
httpOnly
:
true
,
...
...
server/src/api/auth/index.js
View file @
6918915
...
...
@@ -5,7 +5,7 @@ const authCtrl = require('./auth.ctrl')
const
auth
=
new
Router
()
/**
* 회원가입 (email type) : 환자 회원가입
*
로컬
회원가입 (email type) : 환자 회원가입
* url : http://localhost:4000/api/auth/register
* request parameter : userId, password, passwordCheck
* return : null
...
...
@@ -21,7 +21,7 @@ auth.post('/register', authCtrl.register)
auth
.
get
(
'/hospital'
,
authCtrl
.
searchHospital
);
/**
* 회원가입 (email type) : 의사 회원가입
*
로컬
회원가입 (email type) : 의사 회원가입
* url : http://localhost:4000/api/auth/register/doctor
* request parameter : userId, password, passwordCheck, doctorInfo(File)
* return : null
...
...
@@ -29,14 +29,30 @@ auth.get('/hospital', authCtrl.searchHospital);
auth
.
post
(
'/register/doctor'
,
KoaBody
,
authCtrl
.
doctorRegister
)
/**
* 로그인 (email type)
* 로
컬 로
그인 (email type)
* url : http://localhost:4000/api/auth/login
* request parameter : userId, password
* return :
userI
d
* return :
token, userTypeC
d
*/
auth
.
post
(
'/login'
,
authCtrl
.
login
)
/**
* 소셜 회원가입(Google, Naver, Kakao)
* url : http://localhost:4000/api/auth/register/${socialType}
* request parameter : accessToken
* return : status
*/
auth
.
post
(
'/register/social/:socialType'
,
authCtrl
.
socialRegister
);
/**
* 소셜 로그인(Google, Naver, Kakao)
* url : http://localhost:4000/api/auth/login/${socialType}
* request parameter
* return : token, userTypeCd
*/
auth
.
post
(
'/login/social/:socialType'
,
authCtrl
.
socialLogin
);
/**
* 로그아웃
* url : http://localhost:4000/api/auth/logout
* request parameter : null
...
...
server/src/api/doctor/doctor.ctrl.js
View file @
6918915
...
...
@@ -15,6 +15,7 @@ const jwt = require('jsonwebtoken');
const
{
uploadQrCode
,
viewQrCode
}
=
require
(
'../../util/GoogleCloudStorage'
);
const
QrCodeUtil
=
require
(
'../../util/QrCodeUtil'
);
const
{
sendPushMessage
}
=
require
(
'../../util/FCM'
);
/**
...
...
@@ -341,7 +342,19 @@ exports.writeReqBottleFeedback = async ctx => {
doctorId
:
userId
,
feedback
,
});
newFeedback
.
save
();
await
newFeedback
.
save
();
//feedback 알람 보내기
const
hub
=
await
Hub
.
findOne
({
hubId
:
bottle
.
hubId
});
const
patientProfile
=
await
Profile
.
findOne
({
userId
:
hub
.
userId
});
if
(
patientProfile
)
{
sendPushMessage
({
deviceToken
:
patientProfile
.
deviceToken
,
title
:
'의사에게 새로운 알람이 도착했습니다.'
,
body
:
feedback
,
});
}
ctx
.
status
=
200
;
...
...
server/src/lib/jwtMiddleWare.js
View file @
6918915
...
...
@@ -8,6 +8,7 @@ const jwtMiddleware = async (ctx, next) => {
}
try
{
// eslint-disable-next-line no-undef
const
decoded
=
jwt
.
verify
(
token
,
process
.
env
.
JWT_SECRET
);
ctx
.
state
.
user
=
{
_id
:
decoded
.
_id
,
...
...
server/src/models/user.js
View file @
6918915
...
...
@@ -5,9 +5,10 @@ const jwt = require('jsonwebtoken');
const
Schema
=
mongoose
.
Schema
;
const
UserSchema
=
new
Schema
({
userId
:
{
type
:
String
,
required
:
true
,
unique
:
true
,
lowercase
:
true
,
},
hashedPassword
:
{
type
:
String
,
required
:
true
},
userTypeCd
:
{
type
:
String
,
required
:
true
,
default
:
'NORMAL'
},
userId
:
{
type
:
String
,
required
:
true
,
unique
:
true
,
lowercase
:
true
,
trim
:
true
},
hashedPassword
:
{
type
:
String
,
required
:
true
,
},
userTypeCd
:
{
type
:
String
,
required
:
true
,
default
:
'NORMAL'
,
uppercase
:
true
,
},
authTypeCd
:
{
type
:
String
,
required
:
true
,
default
:
'NORMAL'
,
uppercase
:
true
,
},
useYn
:
{
type
:
String
,
default
:
'W'
,
required
:
true
,
},
});
...
...
server/src/util/Batch.js
View file @
6918915
...
...
@@ -20,20 +20,6 @@ const updateMedicineInfo = require('../lib/UpdatingMedicineInfo');
const
{
sendPushMessage
}
=
require
(
'./FCM'
);
// //매년 1월 1일 00시 00분에 1살씩 추가
// exports.CheckNewYear = () => {
// cron.schedule('0 0 0 1 1 *', async () => {
// const profileList = await Profile.find();
// profileList.forEach(async profile => {
// await profile.updateUserAge();
// profile.save();
// });
// }, {
// timezone : 'Asia/Tokyo',
// });
// };
//매월 1일 0시 0분에 약 정보 업데이트
exports
.
updateMedicineData
=
async
()
=>
{
cron
.
schedule
(
'0 0 0 1 * *'
,
()
=>
{
...
...
@@ -76,7 +62,8 @@ exports.pushNotifyByDosage = async() => {
const
medicine
=
await
Medicine
.
findOne
({
medicineId
:
bottleMedicine
.
medicineId
});
pushNotify
({
deviceToken
,
message
:
medicine
.
name
+
'을 복용하셔야 합니다.'
,
title
:
'약 복용 시간입니다'
,
body
:
medicine
.
name
+
'을 복용하셔야 합니다.'
,
});
}
}
...
...
@@ -102,7 +89,8 @@ exports.pushNotifyByDosage = async() => {
const
medicine
=
await
Medicine
.
findOne
({
medicineId
:
bottleMedicine
.
medicineId
});
pushNotify
({
deviceToken
,
message
:
medicine
.
name
+
'을 복용하셔야 합니다.'
,
title
:
'약 복용 시간입니다'
,
body
:
medicine
.
name
+
'을 복용하셔야 합니다.'
,
});
}
}
...
...
@@ -128,7 +116,8 @@ exports.pushNotifyByDosage = async() => {
const
medicine
=
await
Medicine
.
findOne
({
medicineId
:
bottleMedicine
.
medicineId
});
pushNotify
({
deviceToken
,
message
:
medicine
.
name
+
'을 복용하셔야 합니다.'
,
title
:
'약 복용 시간입니다'
,
body
:
medicine
.
name
+
'을 복용하셔야 합니다.'
,
});
}
}
...
...
@@ -139,10 +128,11 @@ exports.pushNotifyByDosage = async() => {
};
const
pushNotify
=
({
deviceToken
,
message
})
=>
{
const
pushNotify
=
({
deviceToken
,
title
,
body
})
=>
{
//toDo : deviceToken을 받아서 push notification을 발송하는 함수
sendPushMessage
({
deviceToken
,
message
,
title
,
body
,
});
};
...
...
server/src/util/DataProcess.js
View file @
6918915
const
BottleMedicine
=
require
(
'../models/bottleMedicine'
);
const
TakeMedicineHist
=
require
(
'../models/takeMedicineHistory'
);
//message subscribe 후 message를 가공한 이후 해당 데이터를 보낼 topic과 message를 리턴하는 함수
exports
.
dataPublish
=
async
(
topic
,
message
)
=>
{
//client가 subscribe를 하면 메시지를 보낸 약병의 topic과 message를 가공 및 보낸 약병의 bottleId를 가져옴
...
...
server/src/util/FCM.js
View file @
6918915
...
...
@@ -7,11 +7,11 @@ exports.initializeFCM = () => {
});
};
exports
.
sendPushMessage
=
async
({
deviceToken
,
message
})
=>
{
exports
.
sendPushMessage
=
async
({
deviceToken
,
title
,
body
})
=>
{
const
notifyMessage
=
{
notification
:
{
title
:
'약 먹을 시간입니다'
,
body
:
message
,
title
,
body
,
},
token
:
deviceToken
,
};
...
...
server/yarn.lock
View file @
6918915
...
...
@@ -2133,10 +2133,17 @@
"string_decoder" "~1.1.1"
"util-deprecate" "~1.0.1"
<<<<<<< HEAD
"readable-stream@~2.3.6":
"integrity" "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw=="
"resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz"
"version" "2.3.7"
=======
"google-auth-library@^7.0.0", "google-auth-library@^7.0.2", "google-auth-library@^7.10.0", "google-auth-library@^7.6.1":
"integrity" "sha512-ICsqaU+lxMHVlDUzMrfVIEqnARw2AwBiZ/2KnNM6BcTf9Nott+Af87DTIzmlnW865p3REUP2MVL0xkPC3a61aQ=="
"resolved" "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.10.0.tgz"
"version" "7.10.0"
>>>>>>> server
dependencies:
"core-util-is" "~1.0.0"
"inherits" "~2.0.3"
...
...
Please
register
or
login
to post a comment