Преглед изворни кода

add apiToken field and methods for token generation and retrieval

reiji-h пре 1 година
родитељ
комит
7bd30fdf01

+ 22 - 0
apps/app/src/server/models/user.js

@@ -68,6 +68,7 @@ const factory = (crowi) => {
     // email: { type: String, required: true, unique: true },
     introduction: String,
     password: String,
+    apiToken: { type: String, index: true },
     lang: {
       type: String,
       enum: i18n.locales,
@@ -146,6 +147,12 @@ const factory = (crowi) => {
     return hasher.digest('hex');
   }
 
+  function generateApiToken(user) {
+    const hasher = crypto.createHash('sha256');
+    hasher.update((new Date()).getTime() + user._id);
+
+    return hasher.digest('base64');
+  }
 
   userSchema.methods.isUniqueEmail = async function() {
     const query = this.model('User').find();
@@ -206,6 +213,14 @@ const factory = (crowi) => {
     return userData;
   };
 
+  userSchema.methods.updateApiToken = async function() {
+    const self = this;
+
+    self.apiToken = generateApiToken(this);
+    const userData = await self.save();
+    return userData;
+  };
+
   // TODO: create UserService and transplant this method because image uploading depends on AttachmentService
   userSchema.methods.updateImage = async function(attachment) {
     this.imageAttachment = attachment;
@@ -431,6 +446,13 @@ const factory = (crowi) => {
     return this.findOne({ username });
   };
 
+  userSchema.statics.findUserByApiToken = function(apiToken) {
+    if (apiToken == null) {
+      return Promise.resolve(null);
+    }
+    return this.findOne({ apiToken }).lean();
+  };
+
   userSchema.statics.findUserByGoogleId = function(googleId, callback) {
     if (googleId == null) {
       callback(null, null);

+ 1 - 0
packages/core/src/interfaces/user.ts

@@ -14,6 +14,7 @@ export type IUser = {
   isGravatarEnabled: boolean,
   admin: boolean,
   readOnly: boolean,
+  apiToken?: string,
   isEmailPublished: boolean,
   isInvitationEmailSended: boolean,
   lang: Lang,

+ 2 - 2
packages/core/src/models/serializers/user-serializer.ts

@@ -3,7 +3,7 @@ import { Document } from 'mongoose';
 import { isPopulated, isRef, type Ref } from '../../interfaces/common';
 import type { IUser } from '../../interfaces/user';
 
-export type IUserSerializedSecurely<U extends IUser> = Omit<U, 'password' | 'email'> & { email?: string };
+export type IUserSerializedSecurely<U extends IUser> = Omit<U, 'password' | 'apiToken' | 'email'> & { email?: string };
 
 export const omitInsecureAttributes = <U extends IUser>(user: U): IUserSerializedSecurely<U> => {
 
@@ -13,7 +13,7 @@ export const omitInsecureAttributes = <U extends IUser>(user: U): IUserSerialize
 
   const {
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
-    password, email, ...rest
+    password, apiToken, email, ...rest
   } = leanDoc;
 
   const secureUser: IUserSerializedSecurely<U> = rest;