Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"permissions": {
"allow": [
"Bash(just nix::develop default bash -c 'just codegen::proto >/dev/null && just codegen::db-schema >/dev/null && echo CODEGEN-OK && just check::test -c backend 2>&1 | tail -40 && just check::lint -c backend 2>&1 | tail -30')",
"Bash(just nix::develop default bash -c 'just check::lint -c backend 2>&1')",
"Bash(just nix::develop default bash -c 'just check::lint -c backend 2>&1 | grep -E \"\\\\.go:[0-9]+|successful|not successful\" ; just check::test -c backend 2>&1 | grep -E \"Ran [0-9]+|Passed|FAIL\"')",
"Bash(nix run *)",
"Bash(git add *)"
]
}
}
76 changes: 76 additions & 0 deletions api/proto/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,12 @@
- [user/messages/user_svc/add_role_response.proto](#user_messages_user_svc_add_role_response-proto)
- [AddRoleResponse](#user-messages-user_svc-AddRoleResponse)

- [user/messages/user_svc/edit_profile_request.proto](#user_messages_user_svc_edit_profile_request-proto)
- [EditProfileRequest](#user-messages-user_svc-EditProfileRequest)

- [user/messages/user_svc/edit_profile_response.proto](#user_messages_user_svc_edit_profile_response-proto)
- [EditProfileResponse](#user-messages-user_svc-EditProfileResponse)

- [user/messages/user_svc/get_request.proto](#user_messages_user_svc_get_request-proto)
- [GetRequest](#user-messages-user_svc-GetRequest)

Expand Down Expand Up @@ -789,6 +795,9 @@ See components/backend/internal/middleware/rbac.go.
| email | [string](#string) | | |
| roles | [GlobalRole](#user-entities-GlobalRole) | repeated | Populated from casbin on fetch; not persisted in ent DB. |
| modified_at | [google.protobuf.Timestamp](#google-protobuf-Timestamp) | | |
| github_url | [string](#string) | | Profile links the user maintains via EditProfile; empty when unset. |
| renku_url | [string](#string) | | |
| linkedin_url | [string](#string) | | |



Expand Down Expand Up @@ -5746,6 +5755,72 @@ casbin role for this hackathon; `is_waiting` is false once approved.



<a name="user_messages_user_svc_edit_profile_request-proto"></a>
<p align="right"><a href="#top">Top</a></p>

## user/messages/user_svc/edit_profile_request.proto



<a name="user-messages-user_svc-EditProfileRequest"></a>

### EditProfileRequest
Edits the caller&#39;s own profile. There is no user id: the target is always
the user the token belongs to. An absent field is left as is; an empty
string clears the link.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| github_url | [string](#string) | optional | |
| renku_url | [string](#string) | optional | |
| linkedin_url | [string](#string) | optional | |















<a name="user_messages_user_svc_edit_profile_response-proto"></a>
<p align="right"><a href="#top">Top</a></p>

## user/messages/user_svc/edit_profile_response.proto



<a name="user-messages-user_svc-EditProfileResponse"></a>

### EditProfileResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| user | [user.entities.User](#user-entities-User) | | |















<a name="user_messages_user_svc_get_request-proto"></a>
<p align="right"><a href="#top">Top</a></p>

Expand Down Expand Up @@ -6068,6 +6143,7 @@ casbin role for this hackathon; `is_waiting` is false once approved.
| Register | [messages.user_svc.RegisterRequest](#user-messages-user_svc-RegisterRequest) | [messages.user_svc.RegisterResponse](#user-messages-user_svc-RegisterResponse) | |
| AddRole | [messages.user_svc.AddRoleRequest](#user-messages-user_svc-AddRoleRequest) | [messages.user_svc.AddRoleResponse](#user-messages-user_svc-AddRoleResponse) | |
| RemoveRole | [messages.user_svc.RemoveRoleRequest](#user-messages-user_svc-RemoveRoleRequest) | [messages.user_svc.RemoveRoleResponse](#user-messages-user_svc-RemoveRoleResponse) | |
| EditProfile | [messages.user_svc.EditProfileRequest](#user-messages-user_svc-EditProfileRequest) | [messages.user_svc.EditProfileResponse](#user-messages-user_svc-EditProfileResponse) | |



Expand Down
4 changes: 4 additions & 0 deletions api/proto/user/entities/user.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ message User {
// Populated from casbin on fetch; not persisted in ent DB.
repeated GlobalRole roles = 7;
google.protobuf.Timestamp modified_at = 8;
// Profile links the user maintains via EditProfile; empty when unset.
string github_url = 9;
string renku_url = 10;
string linkedin_url = 11;
}
14 changes: 14 additions & 0 deletions api/proto/user/messages/user_svc/edit_profile_request.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
syntax = "proto3";

package user.messages.user_svc;

option go_package = "github.com/swissdatasciencecenter/hackagon/components/backend/internal/proto/user/messages/user_svc";

// Edits the caller's own profile. There is no user id: the target is always
// the user the token belongs to. An absent field is left as is; an empty
// string clears the link.
message EditProfileRequest {
optional string github_url = 1;
optional string renku_url = 2;
optional string linkedin_url = 3;
}
11 changes: 11 additions & 0 deletions api/proto/user/messages/user_svc/edit_profile_response.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
syntax = "proto3";

package user.messages.user_svc;

import "user/entities/user.proto";

option go_package = "github.com/swissdatasciencecenter/hackagon/components/backend/internal/proto/user/messages/user_svc";

message EditProfileResponse {
user.entities.User user = 1;
}
3 changes: 3 additions & 0 deletions api/proto/user/user_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package user;

import "user/messages/user_svc/add_role_request.proto";
import "user/messages/user_svc/add_role_response.proto";
import "user/messages/user_svc/edit_profile_request.proto";
import "user/messages/user_svc/edit_profile_response.proto";
import "user/messages/user_svc/get_request.proto";
import "user/messages/user_svc/get_response.proto";
import "user/messages/user_svc/list_request.proto";
Expand All @@ -24,4 +26,5 @@ service UserService {
rpc Register(user.messages.user_svc.RegisterRequest) returns (user.messages.user_svc.RegisterResponse);
rpc AddRole(user.messages.user_svc.AddRoleRequest) returns (user.messages.user_svc.AddRoleResponse);
rpc RemoveRole(user.messages.user_svc.RemoveRoleRequest) returns (user.messages.user_svc.RemoveRoleResponse);
rpc EditProfile(user.messages.user_svc.EditProfileRequest) returns (user.messages.user_svc.EditProfileResponse);
}
3 changes: 3 additions & 0 deletions components/backend/Schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ An authenticated user, synced from Keycloak on first login.
| `keycloak_id` | string | yes | yes | no | no | Unique identifier from Keycloak (sub claim). |
| `display_name` | string | no | no | no | yes | Preferred display name of the user. |
| `email` | string | no | no | no | yes | Email of the user, same as in Keycloak |
| `github_url` | string | no | no | no | yes | Link to the user's GitHub profile, set by the user. |
| `renku_url` | string | no | no | no | yes | Link to the user's Renku profile, set by the user. |
| `linkedin_url` | string | no | no | no | yes | Link to the user's LinkedIn profile, set by the user. |
| `created_at` | time.Time | yes | no | yes | yes | Timestamp when the user was first seen. |
| `modified_at` | time.Time | yes | no | no | yes | Timestamp of the last profile update. |

Expand Down
8 changes: 8 additions & 0 deletions components/backend/db/schema/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ func (User) Fields() []ent.Field {
Comment("Preferred display name of the user."),
field.String("email").Optional().Default("").
Comment("Email of the user, same as in Keycloak"),
// The profile links below are owned by the platform, not Keycloak: the
// user edits them here, and the claim sync on login never touches them.
field.String("github_url").Optional().Default("").
Comment("Link to the user's GitHub profile, set by the user."),
field.String("renku_url").Optional().Default("").
Comment("Link to the user's Renku profile, set by the user."),
field.String("linkedin_url").Optional().Default("").
Comment("Link to the user's LinkedIn profile, set by the user."),
field.Time("created_at").Immutable().Default(time.Now).
Comment("Timestamp when the user was first seen."),
field.Time("modified_at").
Expand Down
3 changes: 3 additions & 0 deletions components/backend/ent/migrate/schema.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading