Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
a02388f
Initial setup and cleaup for admin-app and admin-lib:
MarcelGeo Aug 9, 2024
17a2fc8
Merge pull request #262 from MerginMaps/initial-admin-redesign
MarcelGeo Aug 14, 2024
55e0900
Merge remote-tracking branch 'origin/develop' into develop-redesign-a…
MarcelGeo Sep 13, 2024
c47b364
Improve searching + added reation date to User
MarcelGeo Sep 13, 2024
658f113
Added:
MarcelGeo Sep 13, 2024
63e9548
Fix lint
MarcelGeo Sep 13, 2024
32c933b
Merge remote-tracking branch 'origin/develop' into develop-redesign-a…
MarcelGeo Sep 16, 2024
559a073
Merge branch 'develop-redesign-admin' into redesign-admin-users
MarcelGeo Sep 16, 2024
b0e18a8
Update filtering for projects in admin
MarcelGeo Sep 17, 2024
57ddcc4
Update projects
MarcelGeo Sep 17, 2024
a9e547b
Fix tests for unify tests
MarcelGeo Sep 17, 2024
7bb6539
Fix items instead users
MarcelGeo Sep 17, 2024
701c70e
Fix tests for projects items
MarcelGeo Sep 17, 2024
ba825f0
Fix finding by worksapce
MarcelGeo Sep 17, 2024
3a4cbe7
Merge branch 'redesign-admin-users' into redesign-admin-projects
MarcelGeo Sep 17, 2024
eff8d8b
Merge pull request #287 from MerginMaps/redesign-admin-users
MarcelGeo Sep 18, 2024
127f074
Disable editable public private
MarcelGeo Sep 18, 2024
c063721
Merge pull request #289 from MerginMaps/redesign-admin-projects
MarcelGeo Sep 18, 2024
6c80e90
Added:
MarcelGeo Sep 20, 2024
2aba981
Updates for latest server version
MarcelGeo Sep 20, 2024
92d49c8
Cleanup of not necessary components
MarcelGeo Sep 20, 2024
160ee4d
cleanup of lib-vue2
MarcelGeo Sep 20, 2024
6daddde
Added worksapce id to paginated endpoint
MarcelGeo Sep 20, 2024
b18323a
Cleanup unused i18n
MarcelGeo Sep 20, 2024
99200de
Add licenses
MarcelGeo Sep 23, 2024
c48d772
Merge pull request #292 from MerginMaps/redesign-admin-settings
MarcelGeo Sep 23, 2024
71a2088
Merge pull request #293 from MerginMaps/redesign-admin-remove-lib-vue2
MarcelGeo Sep 23, 2024
306bb2e
Merge remote-tracking branch 'origin/develop-redesign-admin' into red…
MarcelGeo Sep 23, 2024
73e7e06
Use workspace_id from db directly
MarcelGeo Sep 23, 2024
0bebc56
Merge pull request #294 from MerginMaps/redesign-admin-add-wsid
MarcelGeo Sep 23, 2024
5982ce0
Merge remote-tracking branch 'origin/master' into develop-redesign-admin
MarcelGeo Oct 15, 2024
6348a84
Initial changes for proect detail files and versions
MarcelGeo Oct 16, 2024
83b47aa
Create project detail subpages
MarcelGeo Oct 21, 2024
bc5e005
Added:
MarcelGeo Oct 23, 2024
115c25d
Add cursor to table row in style (allow customize in other tables in …
MarcelGeo Oct 23, 2024
8e43e15
Do not show profile row if not in router
MarcelGeo Oct 23, 2024
3fdc5a5
Fix: getting changestes arguments in right order
MarcelGeo Oct 23, 2024
09e6d36
Added:
MarcelGeo Oct 23, 2024
80ceeb2
Added:
MarcelGeo Oct 23, 2024
6a4402a
Router for admin app upgrades
MarcelGeo Oct 23, 2024
e7a50bd
Move check for updates to main app vue to check it only once in session
MarcelGeo Oct 23, 2024
672d0d8
Upgrade of vue / dev deps
MarcelGeo Oct 24, 2024
40e3ab8
Update vue / dev dependencies
MarcelGeo Oct 24, 2024
e37de8d
Remove eslint standard vue plugin - no need for current setup
MarcelGeo Oct 24, 2024
27a9e6c
Merge pull request #304 from MerginMaps/redesign-project-detail
MarcelGeo Oct 24, 2024
e09f5db
Fix eslint things
MarcelGeo Oct 24, 2024
d9b1023
Fix eslint sidebar item
MarcelGeo Oct 24, 2024
17cf6fe
change env of esbuild
MarcelGeo Oct 24, 2024
9a01602
Merge remote-tracking branch 'origin/develop-redesign-admin' into dep…
MarcelGeo Oct 24, 2024
ba40659
Merge pull request #305 from MerginMaps/deps-up
MarcelGeo Oct 24, 2024
fcaea9f
Added ability to handle anchor links in sidebar
MarcelGeo Oct 25, 2024
06c1117
added sidebar footer to admin
MarcelGeo Oct 28, 2024
4ba7b29
Merge pull request #306 from MerginMaps/redesign-admin-sidebar-link
MarcelGeo Oct 28, 2024
52862d1
add mohtly contributors count to send_statistics
MarcelGeo Oct 31, 2024
d45724e
Add project versions to monthly contributors
MarcelGeo Nov 4, 2024
eec1deb
Merge pull request #316 from MerginMaps/gh#2578-callhome-contributors
MarcelGeo Nov 5, 2024
c6f98b1
Fix: add link to project version view instead query params
MarcelGeo Nov 7, 2024
b1d085a
Make accordion smaller
MarcelGeo Nov 7, 2024
1ce9f6f
Send ProjectVersion created signal when creating project in tests
harminius Nov 7, 2024
4b44808
Merge branch 'develop' into create_project_signal
harminius Nov 7, 2024
8b6e8ec
Allow searching users based on first name and last name
MarcelGeo Nov 8, 2024
f091e73
Addressing comments for admin redesign @tomasMizera
MarcelGeo Nov 8, 2024
d618ec1
Introduce ENABLE_SUPERADMIN_ASSIGNMENT variable
MarcelGeo Nov 11, 2024
8c4915c
Deactivate advanced part of account detail for current user
MarcelGeo Nov 11, 2024
e1eb0c8
cleanup unused imports
harminius Nov 11, 2024
489e8b0
send project_version.created signal on pv init
harminius Nov 11, 2024
3a1cac4
Remove prints
MarcelGeo Nov 11, 2024
45444a0
Merge pull request #322 from MerginMaps/redesign-final-1
MarcelGeo Nov 11, 2024
1eb1070
Merge pull request #320 from MerginMaps/create_project_signal
MarcelGeo Nov 11, 2024
65b4ac8
Merge
MarcelGeo Nov 11, 2024
e49e011
Merge pull request #323 from MerginMaps/gh#2610-enable-assignment-var…
MarcelGeo Nov 11, 2024
0c9ad90
Fix imports after merge conflicts
MarcelGeo Nov 11, 2024
65a5c67
Merge remote-tracking branch 'origin/develop' into develop-redesign-a…
MarcelGeo Nov 11, 2024
0f6ce55
Flush to DB right after project is created
harminius Nov 11, 2024
809d93b
Fix merge conflicts projects_query
MarcelGeo Nov 11, 2024
92c2eb3
Add searching text fo projects
MarcelGeo Nov 12, 2024
199c316
cleanup
harminius Nov 12, 2024
598d4ce
we don't need flush in the controller
harminius Nov 12, 2024
61448dc
Merge pull request #327 from MerginMaps/redesign-admin-search-text
MarcelGeo Nov 12, 2024
ee90a3e
Merge pull request #326 from MerginMaps/create_project_signal
MarcelGeo Nov 12, 2024
93d9624
Merge remote-tracking branch 'origin/develop' into develop-redesign-a…
MarcelGeo Nov 12, 2024
d2fdada
Revert "Create project in tests"
MarcelGeo Nov 12, 2024
31ff49d
Merge pull request #328 from MerginMaps/revert-320-create_project_signal
MarcelGeo Nov 12, 2024
190bec5
Merge remote-tracking branch 'origin/develop' into develop-redesign-a…
MarcelGeo Nov 12, 2024
777e0b6
Merge pull request #324 from MerginMaps/develop-redesign-admin
MarcelGeo Nov 12, 2024
83cfacf
Set proper project version type in flask cmd
varmar05 Nov 13, 2024
c8a7654
Merge pull request #330 from MerginMaps/fix_download_cmd
MarcelGeo Nov 13, 2024
84141dc
fix spelling of template
MarcelGeo Nov 18, 2024
16185da
Remove pretty text wrap froom span
MarcelGeo Nov 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions server/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

Configuration.SERVER_TYPE = "ce"
Configuration.USER_SELF_REGISTRATION = False

application = create_app(
[
"DOCS_URL",
Expand All @@ -37,6 +38,7 @@
"GLOBAL_ADMIN",
"GLOBAL_READ",
"GLOBAL_WRITE",
"ENABLE_SUPERADMIN_ASSIGNMENT",
]
)
register_stats(application)
Expand Down
9 changes: 7 additions & 2 deletions server/mergin/auth/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ paths:
count:
type: integer
example: 10
users:
items:
type: array
items:
$ref: "#/components/schemas/User"
Expand Down Expand Up @@ -670,6 +670,11 @@ components:
type: string
format: date-time
example: 2023-07-30T08:47:58Z
registration_date:
nullable: true
type: string
format: date-time
example: 2023-07-30T08:47:58Z
profile:
$ref: "#/components/schemas/UserProfile"
PaginatedUsers:
Expand Down Expand Up @@ -839,4 +844,4 @@ components:
- editor
- reader
- guest
example: reader
example: reader
22 changes: 16 additions & 6 deletions server/mergin/auth/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import pytz
from datetime import datetime, timedelta
from connexion import NoContent
from sqlalchemy import func, desc, asc
from sqlalchemy import func, desc, asc, or_
from sqlalchemy.sql.operators import is_
from flask import request, current_app, jsonify, abort, render_template
from flask_login import login_user, logout_user, current_user
Expand All @@ -23,7 +23,7 @@
user_account_closed,
)
from .bearer import encode_token
from .models import User, LoginHistory
from .models import User, LoginHistory, UserProfile
from .schemas import UserSchema, UserSearchSchema, UserProfileSchema, UserInfoSchema
from .forms import (
LoginForm,
Expand Down Expand Up @@ -408,11 +408,17 @@ def update_user(username): # pylint: disable=W0613,W0612
form = UserForm.from_json(request.json)
if not form.validate_on_submit():
return jsonify(form.errors), 400
if request.json.get("is_admin") is not None and not current_app.config.get(
"ENABLE_SUPERADMIN_ASSIGNMENT"
):
abort(400, "Unable to assign super admin role")

user = User.query.filter_by(username=username).first_or_404("User not found")
form.update_obj(user)

# remove inactive since flag for ban or re-activation
user.inactive_since = None

db.session.add(user)
db.session.commit()
return jsonify(UserSchema().dump(user))
Expand Down Expand Up @@ -449,13 +455,17 @@ def get_paginated_users(

:rtype: Dict[str: List[User], str: Integer]
"""
users = User.query.filter(
users = User.query.join(UserProfile).filter(
is_(User.username.ilike("deleted_%"), False) | is_(User.active, True)
)

if like:
attr = User.email if "@" in like else User.username
users = users.filter(attr.ilike(f"%{like}%"))
users = users.filter(
User.username.ilike(f"%{like}%")
| User.email.ilike(f"%{like}%")
| UserProfile.first_name.ilike(f"%{like}%")
| UserProfile.last_name.ilike(f"%{like}%")
)

if descending and order_by:
users = users.order_by(desc(User.__table__.c[order_by]))
Expand All @@ -467,7 +477,7 @@ def get_paginated_users(

result_users = UserSchema(many=True).dump(result)

data = {"users": result_users, "total": total}
data = {"items": result_users, "count": total}
return data, 200


Expand Down
1 change: 1 addition & 0 deletions server/mergin/auth/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class Meta:
"verified_email",
"profile",
"scheduled_removal",
"registration_date",
)
load_instance = True

Expand Down
4 changes: 4 additions & 0 deletions server/mergin/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ class Configuration(object):

# build hash number
BUILD_HASH = config("BUILD_HASH", default="")
# Allow changing access to admin panel
ENABLE_SUPERADMIN_ASSIGNMENT = config(
"ENABLE_SUPERADMIN_ASSIGNMENT", default=True, cast=bool
)
# backend version
VERSION = config("VERSION", default=get_version())
SERVER_TYPE = config("SERVER_TYPE", default="ce")
1 change: 1 addition & 0 deletions server/mergin/stats/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def send_statistics():
"workspaces_count": current_app.ws_handler.workspace_count(),
"last_change": str(last_change_item.updated) + "Z" if last_change_item else "",
"server_version": current_app.config["VERSION"],
"monthly_contributors": current_app.ws_handler.monthly_contributors_count(),
}

try:
Expand Down
2 changes: 1 addition & 1 deletion server/mergin/sync/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def create(name, namespace, user): # pylint: disable=W0612

@project.command()
@click.argument("project-name")
@click.option("--version", required=True)
@click.option("--version", type=int, required=True)
@click.option("--directory", type=click.Path(), required=True)
def download(project_name, version, directory): # pylint: disable=W0612
"""Download files for project at particular version"""
Expand Down
7 changes: 7 additions & 0 deletions server/mergin/sync/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@ def workspace_count():
"""
pass

@staticmethod
def monthly_contributors_count():
"""
Return number of workspace contributors in current month and year
"""
pass


class AbstractProjectHandler(ABC):
@abstractmethod
Expand Down
1 change: 0 additions & 1 deletion server/mergin/sync/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

from .files import (
File,
UploadFile,
UploadChanges,
ChangesSchema,
ProjectFile,
Expand Down
29 changes: 11 additions & 18 deletions server/mergin/sync/private_api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -183,20 +183,13 @@ paths:
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
- $ref: "#/components/parameters/OrderParams"
- name: name
- name: like
in: query
description: Filter projects by name with ilike pattern
description: Filter projects by name or workspace name with ilike pattern
required: false
schema:
type: string
example: survey
- name: workspace
in: query
description: Filter projects by workspace with ilike pattern
required: false
schema:
type: string
example: my-workspace
responses:
"200":
description: List of projects
Expand All @@ -209,7 +202,7 @@ paths:
type: integer
description: Total number of all projects
example: 20
projects:
items:
type: array
items:
$ref: "#/components/schemas/ProjectListItem"
Expand Down Expand Up @@ -292,7 +285,7 @@ paths:
id:
type: string
format: uuid
example: 'd4ecda97-0595-40af-892c-e7522de70bd2'
example: "d4ecda97-0595-40af-892c-e7522de70bd2"
name:
type: string
example: survey
Expand Down Expand Up @@ -460,7 +453,7 @@ components:
- detail
UsersLimitHit:
allOf:
- $ref: '#/components/schemas/CustomError'
- $ref: "#/components/schemas/CustomError"
type: object
properties:
rejected_emails:
Expand All @@ -473,7 +466,7 @@ components:
example:
code: UsersLimitHit
detail: Maximum number of people in this workspace is reached. Please upgrade your subscription to add more people (UsersLimitHit)
rejected_emails: [ rejected@example.com ]
rejected_emails: [rejected@example.com]
users_quota: 6
ProjectAccessRequestList:
type: array
Expand All @@ -488,7 +481,7 @@ components:
project_id:
type: string
format: uuid
example: 'd4ecda97-0595-40af-892c-e7522de70bd2'
example: "d4ecda97-0595-40af-892c-e7522de70bd2"
project_name:
type: string
example: survey
Expand Down Expand Up @@ -619,25 +612,25 @@ components:
nullable: false
items:
type: string
example: [ john.doe ]
example: [john.doe]
writersnames:
type: array
nullable: false
items:
type: string
example: [ john.doe ]
example: [john.doe]
editorsnames:
type: array
nullable: false
items:
type: string
example: [ john.doe ]
example: [john.doe]
readersnames:
nullable: false
type: array
items:
type: string
example: [ john.doe ]
example: [john.doe]
public:
type: boolean
example: true
Expand Down
8 changes: 3 additions & 5 deletions server/mergin/sync/private_api_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,8 @@ def list_namespace_project_access_requests(


@auth_required(permissions=["admin"])
def list_projects(
page, per_page, order_params=None, name=None, workspace=None
): # noqa: E501
projects = current_app.ws_handler.projects_query(name, workspace)
def list_projects(page, per_page, order_params=None, like=None): # noqa: E501
projects = current_app.ws_handler.projects_query(like)
# do not fetch from db what is not needed
projects = projects.options(
defer(Project.storage_params),
Expand All @@ -211,7 +209,7 @@ def list_projects(
result = projects.paginate(page, per_page).items
total = projects.paginate(page, per_page).total
data = AdminProjectSchema(many=True).dump(result)
data = {"projects": data, "count": total}
data = {"items": data, "count": total}
return data, 200


Expand Down
4 changes: 2 additions & 2 deletions server/mergin/sync/public_api_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ def add_project(namespace): # noqa: E501

p = Project(**request.json, creator=current_user, workspace=workspace)
p.updated = datetime.utcnow()
db.session.add(p)
pa = ProjectAccess(p, public=request.json.get("public", False))

template_name = request.json.get("template", None)
Expand Down Expand Up @@ -230,7 +231,6 @@ def add_project(namespace): # noqa: E501
get_device_id(request),
)

db.session.add(p)
db.session.add(pa)
db.session.add(version)
db.session.commit()
Expand Down Expand Up @@ -1186,6 +1186,7 @@ def clone_project(namespace, project_name): # noqa: E501
workspace=ws,
)
p.updated = datetime.utcnow()
db.session.add(p)
pa = ProjectAccess(p, public=False)

try:
Expand All @@ -1211,7 +1212,6 @@ def clone_project(namespace, project_name): # noqa: E501
user_agent,
device_id,
)
db.session.add(p)
db.session.add(pa)
db.session.add(project_version)
db.session.commit()
Expand Down
3 changes: 2 additions & 1 deletion server/mergin/sync/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,8 @@ class Meta:
class AdminProjectSchema(ma.SQLAlchemyAutoSchema):
id = fields.UUID(attribute="Project.id")
name = fields.Str(attribute="Project.name")
namespace = fields.Method("_workspace_name")
workspace = fields.Method("_workspace_name")
workspace_id = fields.Int(attribute="Project.workspace_id")
version = fields.Function(
lambda obj: ProjectVersion.to_v_name(obj.Project.latest_version)
)
Expand Down
40 changes: 31 additions & 9 deletions server/mergin/sync/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@
#
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial

from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from typing import Dict, Tuple, Optional, Set, List
from flask_login import current_user
from sqlalchemy import or_, and_, Column, literal
from sqlalchemy import or_, and_, Column, literal, extract
from sqlalchemy.orm import joinedload

from .errors import UpdateProjectAccessError
from .models import Project, ProjectAccess, AccessRequest, ProjectAccessDetail
from .models import (
Project,
ProjectAccess,
AccessRequest,
ProjectAccessDetail,
ProjectVersion,
)
from .permissions import projects_query, ProjectPermissions
from .public_api_controller import parse_project_access_update_request
from .. import db
Expand Down Expand Up @@ -248,16 +254,32 @@ def filter_projects(
def workspace_count():
return 1

def projects_query(self, name=None, workspace=None):
@staticmethod
def monthly_contributors_count():
today = datetime.now(timezone.utc)
year = today.year
month = today.month
return (
db.session.query(ProjectVersion.author_id)
.filter(
extract("year", ProjectVersion.created) == year,
extract("month", ProjectVersion.created) == month,
)
.group_by(ProjectVersion.author_id)
.count()
)

def projects_query(self, like: str = None):
ws = self.factory_method()
query = db.session.query(
Project, literal(ws.name).label("workspace_name")
Project,
literal(ws.name).label("workspace_name"),
).filter(Project.storage_params.isnot(None))

if name:
query = query.filter(Project.name.ilike(f"%{name}%"))
if workspace:
query = query.filter(literal(ws.name).ilike(f"%{workspace}%"))
if like:
query = query.filter(
Project.name.ilike(f"%{like}%") | literal(ws.name).ilike(f"%{like}%")
)
return query

@staticmethod
Expand Down
Loading