Skip to content

Commit

Permalink
feat
Browse files Browse the repository at this point in the history
  • Loading branch information
ddadaal committed Apr 25, 2023
1 parent 0b04138 commit cafbc90
Show file tree
Hide file tree
Showing 11 changed files with 63 additions and 19 deletions.
7 changes: 7 additions & 0 deletions .changeset/cuddly-lobsters-pump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@scow/auth": minor
"@scow/lib-auth": minor
"@scow/docs": minor
---

认证系统 GET /user API 增加返回用户姓名和邮箱
8 changes: 7 additions & 1 deletion apps/auth/src/auth/AuthProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,16 @@ export type ValidateNameResult = "NotFound" | "Match" | "NotMatch";
export type CreateUserResult = "AlreadyExists" | "OK";
export type ChangePasswordResult = "NotFound" | "WrongOldPassword" | "OK";

export interface UserInfo {
identityId: string;
name?: string;
mail?: string;
}

export interface AuthProvider {
serveLoginHtml: (callbackUrl: string, req: FastifyRequest, rep: FastifyReply) => Promise<void>;
fetchAuthTokenInfo: (token: string, req: FastifyRequest) => Promise<string | undefined>;
getUser: undefined | ((identityId: string, req: FastifyRequest) => Promise<{ identityId: string } | undefined>);
getUser: undefined | ((identityId: string, req: FastifyRequest) => Promise<UserInfo | undefined>);
createUser: undefined | ((info: CreateUserInfo, req: FastifyRequest) => Promise<CreateUserResult>);
validateName: undefined | ((identityId: string, name: string, req: FastifyRequest) => Promise<ValidateNameResult>);
changePassword: undefined | ((id: string, oldPassword: string, newPassword: string,
Expand Down
5 changes: 3 additions & 2 deletions apps/auth/src/auth/ldap/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,10 @@ export const extractUserInfoFromEntry = (
return undefined;
}

const name = config.attrs.name ? takeOne(extractAttr(entry, config.attrs.name)) : identityId;
const name = config.attrs.name ? takeOne(extractAttr(entry, config.attrs.name)) : undefined;
const mail = config.attrs.mail ? takeOne(extractAttr(entry, config.attrs.mail)) : undefined;

return { identityId, name };
return { identityId, name, mail };
};

export function takeOne(val: string | string[] | undefined) {
Expand Down
21 changes: 16 additions & 5 deletions apps/auth/src/auth/ssh/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,30 @@ export const createSshAuthProvider = (f: FastifyInstance) => {

registerPostHandler(f, loginNode);

return <AuthProvider>{
return {
serveLoginHtml: (callbackUrl, req, rep) => serveLoginHtml(false, callbackUrl, req, rep),
fetchAuthTokenInfo: async () => undefined,
getUser: async (identityId, req) => {
return await sshConnect(loginNode, "root", rootKeyPair, req.log, async (ssh) => {
return loggedExec(ssh, req.log, true, "id", [identityId])
.then(() => ({ identityId }))
.catch(() => undefined);

const resp = await loggedExec(ssh, req.log, false, "getent", ["passwd", identityId]);

if (resp.code !== 0) { return undefined; }

// https://en.wikipedia.org/wiki/Gecos_field
// ddadaal:x:1000:1000::/home/ddadaal:/bin/zsh
const gecosField = resp.stdout.split(":")[4];
const fullName = gecosField.split(",")[0];

return {
identityId,
name: fullName,
};
});
},
validateName: undefined,
createUser: undefined,
changePassword: undefined,
};
} satisfies AuthProvider;

};
8 changes: 6 additions & 2 deletions apps/auth/src/routes/getUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ const QuerystringSchema = Type.Object({
});

const ResponsesSchema = Type.Object({
200: Type.Object({ user: Type.Object({ identityId: Type.String() }) }),
200: Type.Object({ user: Type.Object({
identityId: Type.String(),
name: Type.Optional(Type.String()),
mail: Type.Optional(Type.String()),
}) }),
404: Type.Object({ code: Type.Literal("USER_NOT_FOUND") }),
501: Type.Null({ description: "此功能在当前服务器配置下不可用" }),
});
Expand Down Expand Up @@ -48,7 +52,7 @@ export const getUserRoute = fp(async (f) => {
const result = await f.auth.getUser(identityId, req);

if (result) {
return rep.code(200).send({ user: { identityId: result.identityId } });
return rep.code(200).send({ user: result });
} else {
return rep.code(404).send({ code: "USER_NOT_FOUND" });
}
Expand Down
10 changes: 8 additions & 2 deletions apps/auth/tests/ldap/ldap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ const user = {
captchaCode: "captchaCode",
};

const savedUserMail = "mail is " + user.mail;

class ConfigNoAddUserError extends Error {}

if (!ldap.addUser) {
Expand Down Expand Up @@ -117,6 +119,7 @@ it("creates user and group if groupStrategy is newGroupPerUser", async () => {
expect(responseUser).toEqual({
dn: userDn,
identityId: user.identityId,
mail: savedUserMail,
name: user.name,
});

Expand Down Expand Up @@ -201,7 +204,6 @@ it("should login with correct username and password", async () => {
await createUser();



// login
const { payload, headers } = createFormData({
username: user.identityId,
Expand Down Expand Up @@ -258,7 +260,11 @@ it("gets user info", async () => {
});

expect(resp.statusCode).toBe(200);
expect(resp.json()).toEqual({ user: { identityId: user.identityId } });
expect(resp.json()).toEqual({ user: {
identityId: user.identityId,
name: user.name,
mail: savedUserMail,
} });
});

it("returns 404 if user doesn't exist", async () => {
Expand Down
5 changes: 4 additions & 1 deletion apps/auth/tests/ssh.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ it("gets user info", async () => {
});

expect(resp.statusCode).toBe(200);
expect(resp.json()).toEqual({ user: { identityId: username } });
expect(resp.json()).toEqual({ user: {
identityId: username,
name: "Linux User",
} });
});

it("returns 404 if user doesn't exist", async () => {
Expand Down
3 changes: 2 additions & 1 deletion docs/docs/deploy/config/auth/ldap.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ LDAP认证系统支持的功能如下表:
| 功能 | 是否支持 |
| ---------------- | ------------------------ |
| 用户登录 ||
| 获取用户信息 ||
| 用户创建 | 如果配置了相关配置即支持 |
| 用户名和姓名验证 ||
| 修改密码 ||
Expand Down Expand Up @@ -120,7 +121,7 @@ ldap:
# 3. 管理系统添加用户时,验证ID和姓名是否匹配
#
# 如果不设置此字段,那么
# 1. 用户姓名为用户的ID
# 1. 用户显示的姓名为用户的ID
# 2. 创建用户时姓名信息填入LDAP
# 3. 管理系统添加用户时,不验证ID与姓名是否匹配
# name: cn
Expand Down
3 changes: 2 additions & 1 deletion docs/docs/deploy/config/auth/ssh.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ title: SSH

SSH认证是非常简单的认证方式。用户可以直接使用和SSH登录集群相同的用户名和密码来登录系统。

在此认证方式中,用户的用户ID为其对应的Linux用户名。
在此认证方式中,用户的用户ID为其对应的Linux用户名,用户的姓名为其对应的Linux用户的[Gecos Field](https://en.wikipedia.org/wiki/Gecos_field)的full name字段

SSH认证方式所支持的功能如下表:

| 功能 | 是否支持 |
| ---------------- | -------- |
| 用户登录 ||
| 获取用户信息 ||
| 用户创建 ||
| 用户名和姓名验证 ||
| 修改密码 ||
Expand Down
10 changes: 6 additions & 4 deletions docs/docs/integration/auth/impl.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,11 @@ SCOW中使用`identityId`标识一个用户,并同时使用此`identityId`作

##### 200 OK

| 字段 | 类型 | 是否必须 | 解释 |
| ----------------- | ------ | -------- | -------------------------------- |
| `user.identityId` | 字符串 || 用户的ID。和请求的identityId一致 |
| 字段 | 类型 | 是否必须 | 解释 |
| ----------------- | ------ | -------- | -------------------------------------------------------------------------- |
| `user.identityId` | 字符串 || 用户的ID。和请求的identityId一致 |
| `user.name` | 字符串 || 用户的姓名。如果认证系统可以获取用户的姓名,则返回。如果不能获取,就不设置 |
| `user.mail` | 字符串 || 用户的邮箱。如果认证系统可以获取用户的邮箱,则返回。如果不能获取,就不设置 |

##### 404 Not Found

Expand All @@ -167,7 +169,7 @@ SCOW中使用`identityId`标识一个用户,并同时使用此`identityId`作

#### 解释

此API可以获取用户的信息,当前返回的用户信息只包含用户的ID。此API也可以用于获取用户是否存在。
此API可以获取用户的信息。此API也可以用于获取用户是否存在。

## 修改密码相关API

Expand Down
2 changes: 2 additions & 0 deletions libs/auth/src/getUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { Logger } from "ts-log";

export interface AuthUserInfo {
identityId: string;
name?: string;
mail?: string;
}

/**
Expand Down

0 comments on commit cafbc90

Please sign in to comment.